LCOV - code coverage report
Current view: top level - net/sunrpc - stats.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 15 95 15.8 %
Date: 2014-04-07 Functions: 2 14 14.3 %
Branches: 6 28 21.4 %

           Branch data     Line data    Source code
       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                 :            : #include <linux/slab.h>
      17                 :            : 
      18                 :            : #include <linux/init.h>
      19                 :            : #include <linux/kernel.h>
      20                 :            : #include <linux/proc_fs.h>
      21                 :            : #include <linux/seq_file.h>
      22                 :            : #include <linux/sunrpc/clnt.h>
      23                 :            : #include <linux/sunrpc/svcsock.h>
      24                 :            : #include <linux/sunrpc/metrics.h>
      25                 :            : #include <linux/rcupdate.h>
      26                 :            : 
      27                 :            : #include "netns.h"
      28                 :            : 
      29                 :            : #define RPCDBG_FACILITY RPCDBG_MISC
      30                 :            : 
      31                 :            : /*
      32                 :            :  * Get RPC client stats
      33                 :            :  */
      34                 :          0 : static int rpc_proc_show(struct seq_file *seq, void *v) {
      35                 :          1 :         const struct rpc_stat   *statp = seq->private;
      36                 :          1 :         const struct rpc_program *prog = statp->program;
      37                 :            :         unsigned int i, j;
      38                 :            : 
      39                 :          1 :         seq_printf(seq,
      40                 :            :                 "net %u %u %u %u\n",
      41                 :            :                         statp->netcnt,
      42                 :            :                         statp->netudpcnt,
      43                 :            :                         statp->nettcpcnt,
      44                 :            :                         statp->nettcpconn);
      45                 :          1 :         seq_printf(seq,
      46                 :            :                 "rpc %u %u %u\n",
      47                 :            :                         statp->rpccnt,
      48                 :            :                         statp->rpcretrans,
      49                 :            :                         statp->rpcauthrefresh);
      50                 :            : 
      51         [ +  + ]:          7 :         for (i = 0; i < prog->nrvers; i++) {
      52                 :          5 :                 const struct rpc_version *vers = prog->version[i];
      53         [ +  + ]:          5 :                 if (!vers)
      54                 :          3 :                         continue;
      55                 :          2 :                 seq_printf(seq, "proc%u %u",
      56                 :            :                                         vers->number, vers->nrprocs);
      57         [ +  + ]:         62 :                 for (j = 0; j < vers->nrprocs; j++)
      58                 :         60 :                         seq_printf(seq, " %u",
      59                 :         60 :                                         vers->procs[j].p_count);
      60                 :          2 :                 seq_putc(seq, '\n');
      61                 :            :         }
      62                 :          1 :         return 0;
      63                 :            : }
      64                 :            : 
      65                 :          0 : static int rpc_proc_open(struct inode *inode, struct file *file)
      66                 :            : {
      67                 :          1 :         return single_open(file, rpc_proc_show, PDE_DATA(inode));
      68                 :            : }
      69                 :            : 
      70                 :            : static const struct file_operations rpc_proc_fops = {
      71                 :            :         .owner = THIS_MODULE,
      72                 :            :         .open = rpc_proc_open,
      73                 :            :         .read  = seq_read,
      74                 :            :         .llseek = seq_lseek,
      75                 :            :         .release = single_release,
      76                 :            : };
      77                 :            : 
      78                 :            : /*
      79                 :            :  * Get RPC server stats
      80                 :            :  */
      81                 :          0 : void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
      82                 :          0 :         const struct svc_program *prog = statp->program;
      83                 :            :         const struct svc_procedure *proc;
      84                 :            :         const struct svc_version *vers;
      85                 :            :         unsigned int i, j;
      86                 :            : 
      87                 :          0 :         seq_printf(seq,
      88                 :            :                 "net %u %u %u %u\n",
      89                 :            :                         statp->netcnt,
      90                 :            :                         statp->netudpcnt,
      91                 :            :                         statp->nettcpcnt,
      92                 :            :                         statp->nettcpconn);
      93                 :          0 :         seq_printf(seq,
      94                 :            :                 "rpc %u %u %u %u %u\n",
      95                 :            :                         statp->rpccnt,
      96                 :          0 :                         statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
      97                 :            :                         statp->rpcbadfmt,
      98                 :            :                         statp->rpcbadauth,
      99                 :            :                         statp->rpcbadclnt);
     100                 :            : 
     101         [ #  # ]:          0 :         for (i = 0; i < prog->pg_nvers; i++) {
     102 [ #  # ][ #  # ]:          0 :                 if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc))
     103                 :          0 :                         continue;
     104                 :          0 :                 seq_printf(seq, "proc%d %u", i, vers->vs_nproc);
     105         [ #  # ]:          0 :                 for (j = 0; j < vers->vs_nproc; j++, proc++)
     106                 :          0 :                         seq_printf(seq, " %u", proc->pc_count);
     107                 :          0 :                 seq_putc(seq, '\n');
     108                 :            :         }
     109                 :          0 : }
     110                 :            : EXPORT_SYMBOL_GPL(svc_seq_show);
     111                 :            : 
     112                 :            : /**
     113                 :            :  * rpc_alloc_iostats - allocate an rpc_iostats structure
     114                 :            :  * @clnt: RPC program, version, and xprt
     115                 :            :  *
     116                 :            :  */
     117                 :          0 : struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
     118                 :            : {
     119                 :          0 :         return kcalloc(clnt->cl_maxproc, sizeof(struct rpc_iostats), GFP_KERNEL);
     120                 :            : }
     121                 :            : EXPORT_SYMBOL_GPL(rpc_alloc_iostats);
     122                 :            : 
     123                 :            : /**
     124                 :            :  * rpc_free_iostats - release an rpc_iostats structure
     125                 :            :  * @stats: doomed rpc_iostats structure
     126                 :            :  *
     127                 :            :  */
     128                 :          0 : void rpc_free_iostats(struct rpc_iostats *stats)
     129                 :            : {
     130                 :          0 :         kfree(stats);
     131                 :          0 : }
     132                 :            : EXPORT_SYMBOL_GPL(rpc_free_iostats);
     133                 :            : 
     134                 :            : /**
     135                 :            :  * rpc_count_iostats - tally up per-task stats
     136                 :            :  * @task: completed rpc_task
     137                 :            :  * @stats: array of stat structures
     138                 :            :  *
     139                 :            :  * Relies on the caller for serialization.
     140                 :            :  */
     141                 :          0 : void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
     142                 :            : {
     143                 :          0 :         struct rpc_rqst *req = task->tk_rqstp;
     144                 :            :         struct rpc_iostats *op_metrics;
     145                 :            :         ktime_t delta;
     146                 :            : 
     147         [ #  # ]:          0 :         if (!stats || !req)
     148                 :          0 :                 return;
     149                 :            : 
     150                 :          0 :         op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
     151                 :            : 
     152                 :          0 :         op_metrics->om_ops++;
     153                 :          0 :         op_metrics->om_ntrans += req->rq_ntrans;
     154                 :          0 :         op_metrics->om_timeouts += task->tk_timeouts;
     155                 :            : 
     156                 :          0 :         op_metrics->om_bytes_sent += req->rq_xmit_bytes_sent;
     157                 :          0 :         op_metrics->om_bytes_recv += req->rq_reply_bytes_recvd;
     158                 :            : 
     159                 :          0 :         delta = ktime_sub(req->rq_xtime, task->tk_start);
     160                 :          0 :         op_metrics->om_queue = ktime_add(op_metrics->om_queue, delta);
     161                 :            : 
     162                 :          0 :         op_metrics->om_rtt = ktime_add(op_metrics->om_rtt, req->rq_rtt);
     163                 :            : 
     164                 :          0 :         delta = ktime_sub(ktime_get(), task->tk_start);
     165                 :          0 :         op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta);
     166                 :            : }
     167                 :            : EXPORT_SYMBOL_GPL(rpc_count_iostats);
     168                 :            : 
     169                 :          0 : static void _print_name(struct seq_file *seq, unsigned int op,
     170                 :            :                         struct rpc_procinfo *procs)
     171                 :            : {
     172         [ #  # ]:          0 :         if (procs[op].p_name)
     173                 :          0 :                 seq_printf(seq, "\t%12s: ", procs[op].p_name);
     174         [ #  # ]:          0 :         else if (op == 0)
     175                 :          0 :                 seq_printf(seq, "\t        NULL: ");
     176                 :            :         else
     177                 :          0 :                 seq_printf(seq, "\t%12u: ", op);
     178                 :          0 : }
     179                 :            : 
     180                 :          0 : void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
     181                 :            : {
     182                 :          0 :         struct rpc_iostats *stats = clnt->cl_metrics;
     183                 :            :         struct rpc_xprt *xprt;
     184                 :          0 :         unsigned int op, maxproc = clnt->cl_maxproc;
     185                 :            : 
     186         [ #  # ]:          0 :         if (!stats)
     187                 :          0 :                 return;
     188                 :            : 
     189                 :          0 :         seq_printf(seq, "\tRPC iostats version: %s  ", RPC_IOSTATS_VERS);
     190                 :          0 :         seq_printf(seq, "p/v: %u/%u (%s)\n",
     191                 :          0 :                         clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name);
     192                 :            : 
     193                 :            :         rcu_read_lock();
     194                 :          0 :         xprt = rcu_dereference(clnt->cl_xprt);
     195         [ #  # ]:          0 :         if (xprt)
     196                 :          0 :                 xprt->ops->print_stats(xprt, seq);
     197                 :            :         rcu_read_unlock();
     198                 :            : 
     199                 :          0 :         seq_printf(seq, "\tper-op statistics\n");
     200         [ #  # ]:          0 :         for (op = 0; op < maxproc; op++) {
     201                 :          0 :                 struct rpc_iostats *metrics = &stats[op];
     202                 :          0 :                 _print_name(seq, op, clnt->cl_procinfo);
     203                 :          0 :                 seq_printf(seq, "%lu %lu %lu %Lu %Lu %Lu %Lu %Lu\n",
     204                 :            :                                 metrics->om_ops,
     205                 :            :                                 metrics->om_ntrans,
     206                 :            :                                 metrics->om_timeouts,
     207                 :            :                                 metrics->om_bytes_sent,
     208                 :            :                                 metrics->om_bytes_recv,
     209                 :            :                                 ktime_to_ms(metrics->om_queue),
     210                 :            :                                 ktime_to_ms(metrics->om_rtt),
     211                 :            :                                 ktime_to_ms(metrics->om_execute));
     212                 :            :         }
     213                 :            : }
     214                 :            : EXPORT_SYMBOL_GPL(rpc_print_iostats);
     215                 :            : 
     216                 :            : /*
     217                 :            :  * Register/unregister RPC proc files
     218                 :            :  */
     219                 :            : static inline struct proc_dir_entry *
     220                 :            : do_register(struct net *net, const char *name, void *data,
     221                 :            :             const struct file_operations *fops)
     222                 :            : {
     223                 :            :         struct sunrpc_net *sn;
     224                 :            : 
     225                 :            :         dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
     226                 :          0 :         sn = net_generic(net, sunrpc_net_id);
     227                 :          0 :         return proc_create_data(name, 0, sn->proc_net_rpc, fops, data);
     228                 :            : }
     229                 :            : 
     230                 :            : struct proc_dir_entry *
     231                 :          0 : rpc_proc_register(struct net *net, struct rpc_stat *statp)
     232                 :            : {
     233                 :          0 :         return do_register(net, statp->program->name, statp, &rpc_proc_fops);
     234                 :            : }
     235                 :            : EXPORT_SYMBOL_GPL(rpc_proc_register);
     236                 :            : 
     237                 :            : void
     238                 :          0 : rpc_proc_unregister(struct net *net, const char *name)
     239                 :            : {
     240                 :            :         struct sunrpc_net *sn;
     241                 :            : 
     242                 :          0 :         sn = net_generic(net, sunrpc_net_id);
     243                 :          0 :         remove_proc_entry(name, sn->proc_net_rpc);
     244                 :          0 : }
     245                 :            : EXPORT_SYMBOL_GPL(rpc_proc_unregister);
     246                 :            : 
     247                 :            : struct proc_dir_entry *
     248                 :          0 : svc_proc_register(struct net *net, struct svc_stat *statp, const struct file_operations *fops)
     249                 :            : {
     250                 :          0 :         return do_register(net, statp->program->pg_name, statp, fops);
     251                 :            : }
     252                 :            : EXPORT_SYMBOL_GPL(svc_proc_register);
     253                 :            : 
     254                 :            : void
     255                 :          0 : svc_proc_unregister(struct net *net, const char *name)
     256                 :            : {
     257                 :            :         struct sunrpc_net *sn;
     258                 :            : 
     259                 :          0 :         sn = net_generic(net, sunrpc_net_id);
     260                 :          0 :         remove_proc_entry(name, sn->proc_net_rpc);
     261                 :          0 : }
     262                 :            : EXPORT_SYMBOL_GPL(svc_proc_unregister);
     263                 :            : 
     264                 :          0 : int rpc_proc_init(struct net *net)
     265                 :            : {
     266                 :            :         struct sunrpc_net *sn;
     267                 :            : 
     268                 :            :         dprintk("RPC:       registering /proc/net/rpc\n");
     269                 :          0 :         sn = net_generic(net, sunrpc_net_id);
     270                 :          0 :         sn->proc_net_rpc = proc_mkdir("rpc", net->proc_net);
     271         [ #  # ]:          0 :         if (sn->proc_net_rpc == NULL)
     272                 :            :                 return -ENOMEM;
     273                 :            : 
     274                 :          0 :         return 0;
     275                 :            : }
     276                 :            : 
     277                 :          0 : void rpc_proc_exit(struct net *net)
     278                 :            : {
     279                 :            :         dprintk("RPC:       unregistering /proc/net/rpc\n");
     280                 :          0 :         remove_proc_entry("rpc", net->proc_net);
     281                 :          0 : }
     282                 :            : 

Generated by: LCOV version 1.9