LCOV - code coverage report
Current view: top level - net/sunrpc - stats.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 13 143 9.1 %
Date: 2022-03-28 13:20:08 Functions: 2 18 11.1 %
Branches: 1 36 2.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * linux/net/sunrpc/stats.c
       4                 :            :  *
       5                 :            :  * procfs-based user access to generic RPC statistics. The stats files
       6                 :            :  * reside in /proc/net/rpc.
       7                 :            :  *
       8                 :            :  * The read routines assume that the buffer passed in is just big enough.
       9                 :            :  * If you implement an RPC service that has its own stats routine which
      10                 :            :  * appends the generic RPC stats, make sure you don't exceed the PAGE_SIZE
      11                 :            :  * limit.
      12                 :            :  *
      13                 :            :  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <linux/module.h>
      17                 :            : #include <linux/slab.h>
      18                 :            : 
      19                 :            : #include <linux/init.h>
      20                 :            : #include <linux/kernel.h>
      21                 :            : #include <linux/proc_fs.h>
      22                 :            : #include <linux/seq_file.h>
      23                 :            : #include <linux/sunrpc/clnt.h>
      24                 :            : #include <linux/sunrpc/svcsock.h>
      25                 :            : #include <linux/sunrpc/metrics.h>
      26                 :            : #include <linux/rcupdate.h>
      27                 :            : 
      28                 :            : #include <trace/events/sunrpc.h>
      29                 :            : 
      30                 :            : #include "netns.h"
      31                 :            : 
      32                 :            : #define RPCDBG_FACILITY RPCDBG_MISC
      33                 :            : 
      34                 :            : /*
      35                 :            :  * Get RPC client stats
      36                 :            :  */
      37                 :          0 : static int rpc_proc_show(struct seq_file *seq, void *v) {
      38                 :          0 :         const struct rpc_stat   *statp = seq->private;
      39                 :          0 :         const struct rpc_program *prog = statp->program;
      40                 :          0 :         unsigned int i, j;
      41                 :            : 
      42                 :          0 :         seq_printf(seq,
      43                 :            :                 "net %u %u %u %u\n",
      44                 :            :                         statp->netcnt,
      45                 :            :                         statp->netudpcnt,
      46                 :            :                         statp->nettcpcnt,
      47                 :            :                         statp->nettcpconn);
      48                 :          0 :         seq_printf(seq,
      49                 :            :                 "rpc %u %u %u\n",
      50                 :            :                         statp->rpccnt,
      51                 :            :                         statp->rpcretrans,
      52                 :            :                         statp->rpcauthrefresh);
      53                 :            : 
      54         [ #  # ]:          0 :         for (i = 0; i < prog->nrvers; i++) {
      55                 :          0 :                 const struct rpc_version *vers = prog->version[i];
      56         [ #  # ]:          0 :                 if (!vers)
      57                 :          0 :                         continue;
      58                 :          0 :                 seq_printf(seq, "proc%u %u",
      59                 :            :                                         vers->number, vers->nrprocs);
      60         [ #  # ]:          0 :                 for (j = 0; j < vers->nrprocs; j++)
      61                 :          0 :                         seq_printf(seq, " %u", vers->counts[j]);
      62                 :          0 :                 seq_putc(seq, '\n');
      63                 :            :         }
      64                 :          0 :         return 0;
      65                 :            : }
      66                 :            : 
      67                 :          0 : static int rpc_proc_open(struct inode *inode, struct file *file)
      68                 :            : {
      69                 :          0 :         return single_open(file, rpc_proc_show, PDE_DATA(inode));
      70                 :            : }
      71                 :            : 
      72                 :            : static const struct proc_ops rpc_proc_ops = {
      73                 :            :         .proc_open      = rpc_proc_open,
      74                 :            :         .proc_read      = seq_read,
      75                 :            :         .proc_lseek     = seq_lseek,
      76                 :            :         .proc_release   = single_release,
      77                 :            : };
      78                 :            : 
      79                 :            : /*
      80                 :            :  * Get RPC server stats
      81                 :            :  */
      82                 :          0 : void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp)
      83                 :            : {
      84                 :          0 :         const struct svc_program *prog = statp->program;
      85                 :          0 :         const struct svc_version *vers;
      86                 :          0 :         unsigned int i, j;
      87                 :            : 
      88                 :          0 :         seq_printf(seq,
      89                 :            :                 "net %u %u %u %u\n",
      90                 :            :                         statp->netcnt,
      91                 :            :                         statp->netudpcnt,
      92                 :            :                         statp->nettcpcnt,
      93                 :            :                         statp->nettcpconn);
      94                 :          0 :         seq_printf(seq,
      95                 :            :                 "rpc %u %u %u %u %u\n",
      96                 :            :                         statp->rpccnt,
      97                 :          0 :                         statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
      98                 :            :                         statp->rpcbadfmt,
      99                 :            :                         statp->rpcbadauth,
     100                 :            :                         statp->rpcbadclnt);
     101                 :            : 
     102         [ #  # ]:          0 :         for (i = 0; i < prog->pg_nvers; i++) {
     103                 :          0 :                 vers = prog->pg_vers[i];
     104         [ #  # ]:          0 :                 if (!vers)
     105                 :          0 :                         continue;
     106                 :          0 :                 seq_printf(seq, "proc%d %u", i, vers->vs_nproc);
     107         [ #  # ]:          0 :                 for (j = 0; j < vers->vs_nproc; j++)
     108                 :          0 :                         seq_printf(seq, " %u", vers->vs_count[j]);
     109                 :          0 :                 seq_putc(seq, '\n');
     110                 :            :         }
     111                 :          0 : }
     112                 :            : EXPORT_SYMBOL_GPL(svc_seq_show);
     113                 :            : 
     114                 :            : /**
     115                 :            :  * rpc_alloc_iostats - allocate an rpc_iostats structure
     116                 :            :  * @clnt: RPC program, version, and xprt
     117                 :            :  *
     118                 :            :  */
     119                 :          0 : struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
     120                 :            : {
     121                 :          0 :         struct rpc_iostats *stats;
     122                 :          0 :         int i;
     123                 :            : 
     124                 :          0 :         stats = kcalloc(clnt->cl_maxproc, sizeof(*stats), GFP_KERNEL);
     125         [ #  # ]:          0 :         if (stats) {
     126         [ #  # ]:          0 :                 for (i = 0; i < clnt->cl_maxproc; i++)
     127                 :          0 :                         spin_lock_init(&stats[i].om_lock);
     128                 :            :         }
     129                 :          0 :         return stats;
     130                 :            : }
     131                 :            : EXPORT_SYMBOL_GPL(rpc_alloc_iostats);
     132                 :            : 
     133                 :            : /**
     134                 :            :  * rpc_free_iostats - release an rpc_iostats structure
     135                 :            :  * @stats: doomed rpc_iostats structure
     136                 :            :  *
     137                 :            :  */
     138                 :          0 : void rpc_free_iostats(struct rpc_iostats *stats)
     139                 :            : {
     140                 :          0 :         kfree(stats);
     141                 :          0 : }
     142                 :            : EXPORT_SYMBOL_GPL(rpc_free_iostats);
     143                 :            : 
     144                 :            : /**
     145                 :            :  * rpc_count_iostats_metrics - tally up per-task stats
     146                 :            :  * @task: completed rpc_task
     147                 :            :  * @op_metrics: stat structure for OP that will accumulate stats from @task
     148                 :            :  */
     149                 :          0 : void rpc_count_iostats_metrics(const struct rpc_task *task,
     150                 :            :                                struct rpc_iostats *op_metrics)
     151                 :            : {
     152                 :          0 :         struct rpc_rqst *req = task->tk_rqstp;
     153                 :          0 :         ktime_t backlog, execute, now;
     154                 :            : 
     155         [ #  # ]:          0 :         if (!op_metrics || !req)
     156                 :            :                 return;
     157                 :            : 
     158                 :          0 :         now = ktime_get();
     159                 :          0 :         spin_lock(&op_metrics->om_lock);
     160                 :            : 
     161                 :          0 :         op_metrics->om_ops++;
     162                 :            :         /* kernel API: om_ops must never become larger than om_ntrans */
     163                 :          0 :         op_metrics->om_ntrans += max(req->rq_ntrans, 1);
     164                 :          0 :         op_metrics->om_timeouts += task->tk_timeouts;
     165                 :            : 
     166                 :          0 :         op_metrics->om_bytes_sent += req->rq_xmit_bytes_sent;
     167                 :          0 :         op_metrics->om_bytes_recv += req->rq_reply_bytes_recvd;
     168                 :            : 
     169                 :          0 :         backlog = 0;
     170         [ #  # ]:          0 :         if (ktime_to_ns(req->rq_xtime)) {
     171                 :          0 :                 backlog = ktime_sub(req->rq_xtime, task->tk_start);
     172                 :          0 :                 op_metrics->om_queue = ktime_add(op_metrics->om_queue, backlog);
     173                 :            :         }
     174                 :            : 
     175                 :          0 :         op_metrics->om_rtt = ktime_add(op_metrics->om_rtt, req->rq_rtt);
     176                 :            : 
     177                 :          0 :         execute = ktime_sub(now, task->tk_start);
     178                 :          0 :         op_metrics->om_execute = ktime_add(op_metrics->om_execute, execute);
     179         [ #  # ]:          0 :         if (task->tk_status < 0)
     180                 :          0 :                 op_metrics->om_error_status++;
     181                 :            : 
     182                 :          0 :         spin_unlock(&op_metrics->om_lock);
     183                 :            : 
     184                 :          0 :         trace_rpc_stats_latency(req->rq_task, backlog, req->rq_rtt, execute);
     185                 :            : }
     186                 :            : EXPORT_SYMBOL_GPL(rpc_count_iostats_metrics);
     187                 :            : 
     188                 :            : /**
     189                 :            :  * rpc_count_iostats - tally up per-task stats
     190                 :            :  * @task: completed rpc_task
     191                 :            :  * @stats: array of stat structures
     192                 :            :  *
     193                 :            :  * Uses the statidx from @task
     194                 :            :  */
     195                 :          0 : void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
     196                 :            : {
     197                 :          0 :         rpc_count_iostats_metrics(task,
     198                 :          0 :                                   &stats[task->tk_msg.rpc_proc->p_statidx]);
     199                 :          0 : }
     200                 :            : EXPORT_SYMBOL_GPL(rpc_count_iostats);
     201                 :            : 
     202                 :          0 : static void _print_name(struct seq_file *seq, unsigned int op,
     203                 :            :                         const struct rpc_procinfo *procs)
     204                 :            : {
     205         [ #  # ]:          0 :         if (procs[op].p_name)
     206                 :          0 :                 seq_printf(seq, "\t%12s: ", procs[op].p_name);
     207         [ #  # ]:          0 :         else if (op == 0)
     208                 :          0 :                 seq_printf(seq, "\t        NULL: ");
     209                 :            :         else
     210                 :          0 :                 seq_printf(seq, "\t%12u: ", op);
     211                 :          0 : }
     212                 :            : 
     213                 :          0 : static void _add_rpc_iostats(struct rpc_iostats *a, struct rpc_iostats *b)
     214                 :            : {
     215                 :          0 :         a->om_ops += b->om_ops;
     216                 :          0 :         a->om_ntrans += b->om_ntrans;
     217                 :          0 :         a->om_timeouts += b->om_timeouts;
     218                 :          0 :         a->om_bytes_sent += b->om_bytes_sent;
     219                 :          0 :         a->om_bytes_recv += b->om_bytes_recv;
     220                 :          0 :         a->om_queue = ktime_add(a->om_queue, b->om_queue);
     221                 :          0 :         a->om_rtt = ktime_add(a->om_rtt, b->om_rtt);
     222                 :          0 :         a->om_execute = ktime_add(a->om_execute, b->om_execute);
     223                 :          0 :         a->om_error_status += b->om_error_status;
     224                 :          0 : }
     225                 :            : 
     226                 :          0 : static void _print_rpc_iostats(struct seq_file *seq, struct rpc_iostats *stats,
     227                 :            :                                int op, const struct rpc_procinfo *procs)
     228                 :            : {
     229                 :          0 :         _print_name(seq, op, procs);
     230                 :          0 :         seq_printf(seq, "%lu %lu %lu %llu %llu %llu %llu %llu %lu\n",
     231                 :            :                    stats->om_ops,
     232                 :            :                    stats->om_ntrans,
     233                 :            :                    stats->om_timeouts,
     234                 :            :                    stats->om_bytes_sent,
     235                 :            :                    stats->om_bytes_recv,
     236                 :            :                    ktime_to_ms(stats->om_queue),
     237                 :            :                    ktime_to_ms(stats->om_rtt),
     238                 :            :                    ktime_to_ms(stats->om_execute),
     239                 :            :                    stats->om_error_status);
     240                 :          0 : }
     241                 :            : 
     242                 :          0 : static int do_print_stats(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *seqv)
     243                 :            : {
     244                 :          0 :         struct seq_file *seq = seqv;
     245                 :            : 
     246                 :          0 :         xprt->ops->print_stats(xprt, seq);
     247                 :          0 :         return 0;
     248                 :            : }
     249                 :            : 
     250                 :          0 : void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt)
     251                 :            : {
     252                 :          0 :         unsigned int op, maxproc = clnt->cl_maxproc;
     253                 :            : 
     254         [ #  # ]:          0 :         if (!clnt->cl_metrics)
     255                 :            :                 return;
     256                 :            : 
     257                 :          0 :         seq_printf(seq, "\tRPC iostats version: %s  ", RPC_IOSTATS_VERS);
     258                 :          0 :         seq_printf(seq, "p/v: %u/%u (%s)\n",
     259                 :          0 :                         clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name);
     260                 :            : 
     261                 :          0 :         rpc_clnt_iterate_for_each_xprt(clnt, do_print_stats, seq);
     262                 :            : 
     263                 :          0 :         seq_printf(seq, "\tper-op statistics\n");
     264         [ #  # ]:          0 :         for (op = 0; op < maxproc; op++) {
     265                 :          0 :                 struct rpc_iostats stats = {};
     266                 :          0 :                 struct rpc_clnt *next = clnt;
     267                 :          0 :                 do {
     268                 :          0 :                         _add_rpc_iostats(&stats, &next->cl_metrics[op]);
     269         [ #  # ]:          0 :                         if (next == next->cl_parent)
     270                 :            :                                 break;
     271                 :          0 :                         next = next->cl_parent;
     272         [ #  # ]:          0 :                 } while (next);
     273                 :          0 :                 _print_rpc_iostats(seq, &stats, op, clnt->cl_procinfo);
     274                 :            :         }
     275                 :            : }
     276                 :            : EXPORT_SYMBOL_GPL(rpc_clnt_show_stats);
     277                 :            : 
     278                 :            : /*
     279                 :            :  * Register/unregister RPC proc files
     280                 :            :  */
     281                 :            : static inline struct proc_dir_entry *
     282                 :         30 : do_register(struct net *net, const char *name, void *data,
     283                 :            :             const struct proc_ops *proc_ops)
     284                 :            : {
     285                 :         30 :         struct sunrpc_net *sn;
     286                 :            : 
     287                 :         30 :         dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
     288                 :         30 :         sn = net_generic(net, sunrpc_net_id);
     289                 :         30 :         return proc_create_data(name, 0, sn->proc_net_rpc, proc_ops, data);
     290                 :            : }
     291                 :            : 
     292                 :            : struct proc_dir_entry *
     293                 :         30 : rpc_proc_register(struct net *net, struct rpc_stat *statp)
     294                 :            : {
     295                 :         30 :         return do_register(net, statp->program->name, statp, &rpc_proc_ops);
     296                 :            : }
     297                 :            : EXPORT_SYMBOL_GPL(rpc_proc_register);
     298                 :            : 
     299                 :            : void
     300                 :          0 : rpc_proc_unregister(struct net *net, const char *name)
     301                 :            : {
     302                 :          0 :         struct sunrpc_net *sn;
     303                 :            : 
     304                 :          0 :         sn = net_generic(net, sunrpc_net_id);
     305                 :          0 :         remove_proc_entry(name, sn->proc_net_rpc);
     306                 :          0 : }
     307                 :            : EXPORT_SYMBOL_GPL(rpc_proc_unregister);
     308                 :            : 
     309                 :            : struct proc_dir_entry *
     310                 :          0 : svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops)
     311                 :            : {
     312                 :          0 :         return do_register(net, statp->program->pg_name, statp, proc_ops);
     313                 :            : }
     314                 :            : EXPORT_SYMBOL_GPL(svc_proc_register);
     315                 :            : 
     316                 :            : void
     317                 :          0 : svc_proc_unregister(struct net *net, const char *name)
     318                 :            : {
     319                 :          0 :         struct sunrpc_net *sn;
     320                 :            : 
     321                 :          0 :         sn = net_generic(net, sunrpc_net_id);
     322                 :          0 :         remove_proc_entry(name, sn->proc_net_rpc);
     323                 :          0 : }
     324                 :            : EXPORT_SYMBOL_GPL(svc_proc_unregister);
     325                 :            : 
     326                 :         30 : int rpc_proc_init(struct net *net)
     327                 :            : {
     328                 :         30 :         struct sunrpc_net *sn;
     329                 :            : 
     330                 :         30 :         dprintk("RPC:       registering /proc/net/rpc\n");
     331                 :         30 :         sn = net_generic(net, sunrpc_net_id);
     332                 :         30 :         sn->proc_net_rpc = proc_mkdir("rpc", net->proc_net);
     333         [ -  + ]:         30 :         if (sn->proc_net_rpc == NULL)
     334                 :          0 :                 return -ENOMEM;
     335                 :            : 
     336                 :            :         return 0;
     337                 :            : }
     338                 :            : 
     339                 :          0 : void rpc_proc_exit(struct net *net)
     340                 :            : {
     341                 :          0 :         dprintk("RPC:       unregistering /proc/net/rpc\n");
     342                 :          0 :         remove_proc_entry("rpc", net->proc_net);
     343                 :          0 : }

Generated by: LCOV version 1.14