Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * linux/net/sunrpc/stats.c
  3  *
  4  * procfs-based user access to generic RPC statistics. The stats files
  5  * reside in /proc/net/rpc.
  6  *
  7  * The read routines assume that the buffer passed in is just big enough.
  8  * If you implement an RPC service that has its own stats routine which
  9  * appends the generic RPC stats, make sure you don't exceed the PAGE_SIZE
 10  * limit.
 11  *
 12  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
 13  */
 14 
 15 #include <linux/module.h>
 16 
 17 #include <linux/init.h>
 18 #include <linux/kernel.h>
 19 #include <linux/proc_fs.h>
 20 #include <linux/seq_file.h>
 21 #include <linux/sunrpc/clnt.h>
 22 #include <linux/sunrpc/svcsock.h>
 23 #include <linux/sunrpc/metrics.h>
 24 #include <net/net_namespace.h>
 25 
 26 #define RPCDBG_FACILITY RPCDBG_MISC
 27 
 28 struct proc_dir_entry   *proc_net_rpc = NULL;
 29 
 30 /*
 31  * Get RPC client stats
 32  */
 33 static int rpc_proc_show(struct seq_file *seq, void *v) {
 34         const struct rpc_stat   *statp = seq->private;
 35         const struct rpc_program *prog = statp->program;
 36         unsigned int i, j;
 37 
 38         seq_printf(seq,
 39                 "net %u %u %u %u\n",
 40                         statp->netcnt,
 41                         statp->netudpcnt,
 42                         statp->nettcpcnt,
 43                         statp->nettcpconn);
 44         seq_printf(seq,
 45                 "rpc %u %u %u\n",
 46                         statp->rpccnt,
 47                         statp->rpcretrans,
 48                         statp->rpcauthrefresh);
 49 
 50         for (i = 0; i < prog->nrvers; i++) {
 51                 const struct rpc_version *vers = prog->version[i];
 52                 if (!vers)
 53                         continue;
 54                 seq_printf(seq, "proc%u %u",
 55                                         vers->number, vers->nrprocs);
 56                 for (j = 0; j < vers->nrprocs; j++)
 57                         seq_printf(seq, " %u",
 58                                         vers->procs[j].p_count);
 59                 seq_putc(seq, '\n');
 60         }
 61         return 0;
 62 }
 63 
 64 static int rpc_proc_open(struct inode *inode, struct file *file)
 65 {
 66         return single_open(file, rpc_proc_show, PDE(inode)->data);
 67 }
 68 
 69 static const struct file_operations rpc_proc_fops = {
 70         .owner = THIS_MODULE,
 71         .open = rpc_proc_open,
 72         .read  = seq_read,
 73         .llseek = seq_lseek,
 74         .release = single_release,
 75 };
 76 
 77 /*
 78  * Get RPC server stats
 79  */
 80 void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
 81         const struct svc_program *prog = statp->program;
 82         const struct svc_procedure *proc;
 83         const struct svc_version *vers;
 84         unsigned int i, j;
 85 
 86         seq_printf(seq,
 87                 "net %u %u %u %u\n",
 88                         statp->netcnt,
 89                         statp->netudpcnt,
 90                         statp->nettcpcnt,
 91                         statp->nettcpconn);
 92         seq_printf(seq,
 93                 "rpc %u %u %u %u %u\n",
 94                         statp->rpccnt,
 95                         statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
 96                         statp->rpcbadfmt,
 97                         statp->rpcbadauth,
 98                         statp->rpcbadclnt);
 99 
100         for (i = 0; i < prog->pg_nvers; i++) {
101                 if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc))
102                         continue;
103                 seq_printf(seq, "proc%d %u", i, vers->vs_nproc);
104                 for (j = 0; j < vers->vs_nproc; j++, proc++)
105                         seq_printf(seq, " %u", proc->pc_count);
106                 seq_putc(seq, '\n');
107         }
108 }
109 EXPORT_SYMBOL(svc_seq_show);
110 
111 /**
112  * rpc_alloc_iostats - allocate an rpc_iostats structure
113  * @clnt: RPC program, version, and xprt
114  *
115  */
116 struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
117 {
118         struct rpc_iostats *new;
119         new = kcalloc(clnt->cl_maxproc, sizeof(struct rpc_iostats), GFP_KERNEL);
120         return new;
121 }
122 EXPORT_SYMBOL_GPL(rpc_alloc_iostats);
123 
124 /**
125  * rpc_free_iostats - release an rpc_iostats structure
126  * @stats: doomed rpc_iostats structure
127  *
128  */
129 void rpc_free_iostats(struct rpc_iostats *stats)
130 {
131         kfree(stats);
132 }
133 EXPORT_SYMBOL_GPL(rpc_free_iostats);
134 
135 /**
136  * rpc_count_iostats - tally up per-task stats
137  * @task: completed rpc_task
138  *
139  * Relies on the caller for serialization.
140  */
141 void rpc_count_iostats(struct rpc_task *task)
142 {
143         struct rpc_rqst *req = task->tk_rqstp;
144         struct rpc_iostats *stats = task->tk_client->cl_metrics;
145         struct rpc_iostats *op_metrics;
146         long rtt, execute, queue;
147 
148         if (!stats || !req)
149                 return;
150         op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
151 
152         op_metrics->om_ops++;
153         op_metrics->om_ntrans += req->rq_ntrans;
154         op_metrics->om_timeouts += task->tk_timeouts;
155 
156         op_metrics->om_bytes_sent += task->tk_bytes_sent;
157         op_metrics->om_bytes_recv += req->rq_received;
158 
159         queue = (long)req->rq_xtime - task->tk_start;
160         if (queue < 0)
161                 queue = -queue;
162         op_metrics->om_queue += queue;
163 
164         rtt = task->tk_rtt;
165         if (rtt < 0)
166                 rtt = -rtt;
167         op_metrics->om_rtt += rtt;
168 
169         execute = (long)jiffies - task->tk_start;
170         if (execute < 0)
171                 execute = -execute;
172         op_metrics->om_execute += execute;
173 }
174 
175 static void _print_name(struct seq_file *seq, unsigned int op,
176                         struct rpc_procinfo *procs)
177 {
178         if (procs[op].p_name)
179                 seq_printf(seq, "\t%12s: ", procs[op].p_name);
180         else if (op == 0)
181                 seq_printf(seq, "\t        NULL: ");
182         else
183                 seq_printf(seq, "\t%12u: ", op);
184 }
185 
186 #define MILLISECS_PER_JIFFY     (1000 / HZ)
187 
188 void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
189 {
190         struct rpc_iostats *stats = clnt->cl_metrics;
191         struct rpc_xprt *xprt = clnt->cl_xprt;
192         unsigned int op, maxproc = clnt->cl_maxproc;
193 
194         if (!stats)
195                 return;
196 
197         seq_printf(seq, "\tRPC iostats version: %s  ", RPC_IOSTATS_VERS);
198         seq_printf(seq, "p/v: %u/%u (%s)\n",
199                         clnt->cl_prog, clnt->cl_vers, clnt->cl_protname);
200 
201         if (xprt)
202                 xprt->ops->print_stats(xprt, seq);
203 
204         seq_printf(seq, "\tper-op statistics\n");
205         for (op = 0; op < maxproc; op++) {
206                 struct rpc_iostats *metrics = &stats[op];
207                 _print_name(seq, op, clnt->cl_procinfo);
208                 seq_printf(seq, "%lu %lu %lu %Lu %Lu %Lu %Lu %Lu\n",
209                                 metrics->om_ops,
210                                 metrics->om_ntrans,
211                                 metrics->om_timeouts,
212                                 metrics->om_bytes_sent,
213                                 metrics->om_bytes_recv,
214                                 metrics->om_queue * MILLISECS_PER_JIFFY,
215                                 metrics->om_rtt * MILLISECS_PER_JIFFY,
216                                 metrics->om_execute * MILLISECS_PER_JIFFY);
217         }
218 }
219 EXPORT_SYMBOL_GPL(rpc_print_iostats);
220 
221 /*
222  * Register/unregister RPC proc files
223  */
224 static inline struct proc_dir_entry *
225 do_register(const char *name, void *data, const struct file_operations *fops)
226 {
227         struct proc_dir_entry *ent;
228 
229         rpc_proc_init();
230         dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
231 
232         ent = proc_create(name, 0, proc_net_rpc, fops);
233         if (ent) {
234                 ent->data = data;
235         }
236         return ent;
237 }
238 
239 struct proc_dir_entry *
240 rpc_proc_register(struct rpc_stat *statp)
241 {
242         return do_register(statp->program->name, statp, &rpc_proc_fops);
243 }
244 EXPORT_SYMBOL_GPL(rpc_proc_register);
245 
246 void
247 rpc_proc_unregister(const char *name)
248 {
249         remove_proc_entry(name, proc_net_rpc);
250 }
251 EXPORT_SYMBOL_GPL(rpc_proc_unregister);
252 
253 struct proc_dir_entry *
254 svc_proc_register(struct svc_stat *statp, const struct file_operations *fops)
255 {
256         return do_register(statp->program->pg_name, statp, fops);
257 }
258 EXPORT_SYMBOL(svc_proc_register);
259 
260 void
261 svc_proc_unregister(const char *name)
262 {
263         remove_proc_entry(name, proc_net_rpc);
264 }
265 EXPORT_SYMBOL(svc_proc_unregister);
266 
267 void
268 rpc_proc_init(void)
269 {
270         dprintk("RPC:       registering /proc/net/rpc\n");
271         if (!proc_net_rpc) {
272                 struct proc_dir_entry *ent;
273                 ent = proc_mkdir("rpc", init_net.proc_net);
274                 if (ent) {
275                         ent->owner = THIS_MODULE;
276                         proc_net_rpc = ent;
277                 }
278         }
279 }
280 
281 void
282 rpc_proc_exit(void)
283 {
284         dprintk("RPC:       unregistering /proc/net/rpc\n");
285         if (proc_net_rpc) {
286                 proc_net_rpc = NULL;
287                 remove_proc_entry("rpc", init_net.proc_net);
288         }
289 }
290 
291 
  This page was automatically generated by the LXR engine.