0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/module.h>
0017 #include <linux/slab.h>
0018
0019 #include <linux/init.h>
0020 #include <linux/kernel.h>
0021 #include <linux/proc_fs.h>
0022 #include <linux/seq_file.h>
0023 #include <linux/sunrpc/clnt.h>
0024 #include <linux/sunrpc/svcsock.h>
0025 #include <linux/sunrpc/metrics.h>
0026 #include <linux/rcupdate.h>
0027
0028 #include <trace/events/sunrpc.h>
0029
0030 #include "netns.h"
0031
0032 #define RPCDBG_FACILITY RPCDBG_MISC
0033
0034
0035
0036
0037 static int rpc_proc_show(struct seq_file *seq, void *v) {
0038 const struct rpc_stat *statp = seq->private;
0039 const struct rpc_program *prog = statp->program;
0040 unsigned int i, j;
0041
0042 seq_printf(seq,
0043 "net %u %u %u %u\n",
0044 statp->netcnt,
0045 statp->netudpcnt,
0046 statp->nettcpcnt,
0047 statp->nettcpconn);
0048 seq_printf(seq,
0049 "rpc %u %u %u\n",
0050 statp->rpccnt,
0051 statp->rpcretrans,
0052 statp->rpcauthrefresh);
0053
0054 for (i = 0; i < prog->nrvers; i++) {
0055 const struct rpc_version *vers = prog->version[i];
0056 if (!vers)
0057 continue;
0058 seq_printf(seq, "proc%u %u",
0059 vers->number, vers->nrprocs);
0060 for (j = 0; j < vers->nrprocs; j++)
0061 seq_printf(seq, " %u", vers->counts[j]);
0062 seq_putc(seq, '\n');
0063 }
0064 return 0;
0065 }
0066
0067 static int rpc_proc_open(struct inode *inode, struct file *file)
0068 {
0069 return single_open(file, rpc_proc_show, pde_data(inode));
0070 }
0071
0072 static const struct proc_ops rpc_proc_ops = {
0073 .proc_open = rpc_proc_open,
0074 .proc_read = seq_read,
0075 .proc_lseek = seq_lseek,
0076 .proc_release = single_release,
0077 };
0078
0079
0080
0081
0082 void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp)
0083 {
0084 const struct svc_program *prog = statp->program;
0085 const struct svc_version *vers;
0086 unsigned int i, j;
0087
0088 seq_printf(seq,
0089 "net %u %u %u %u\n",
0090 statp->netcnt,
0091 statp->netudpcnt,
0092 statp->nettcpcnt,
0093 statp->nettcpconn);
0094 seq_printf(seq,
0095 "rpc %u %u %u %u %u\n",
0096 statp->rpccnt,
0097 statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
0098 statp->rpcbadfmt,
0099 statp->rpcbadauth,
0100 statp->rpcbadclnt);
0101
0102 for (i = 0; i < prog->pg_nvers; i++) {
0103 vers = prog->pg_vers[i];
0104 if (!vers)
0105 continue;
0106 seq_printf(seq, "proc%d %u", i, vers->vs_nproc);
0107 for (j = 0; j < vers->vs_nproc; j++)
0108 seq_printf(seq, " %u", vers->vs_count[j]);
0109 seq_putc(seq, '\n');
0110 }
0111 }
0112 EXPORT_SYMBOL_GPL(svc_seq_show);
0113
0114
0115
0116
0117
0118
0119 struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
0120 {
0121 struct rpc_iostats *stats;
0122 int i;
0123
0124 stats = kcalloc(clnt->cl_maxproc, sizeof(*stats), GFP_KERNEL);
0125 if (stats) {
0126 for (i = 0; i < clnt->cl_maxproc; i++)
0127 spin_lock_init(&stats[i].om_lock);
0128 }
0129 return stats;
0130 }
0131 EXPORT_SYMBOL_GPL(rpc_alloc_iostats);
0132
0133
0134
0135
0136
0137
0138 void rpc_free_iostats(struct rpc_iostats *stats)
0139 {
0140 kfree(stats);
0141 }
0142 EXPORT_SYMBOL_GPL(rpc_free_iostats);
0143
0144
0145
0146
0147
0148
0149 void rpc_count_iostats_metrics(const struct rpc_task *task,
0150 struct rpc_iostats *op_metrics)
0151 {
0152 struct rpc_rqst *req = task->tk_rqstp;
0153 ktime_t backlog, execute, now;
0154
0155 if (!op_metrics || !req)
0156 return;
0157
0158 now = ktime_get();
0159 spin_lock(&op_metrics->om_lock);
0160
0161 op_metrics->om_ops++;
0162
0163 op_metrics->om_ntrans += max(req->rq_ntrans, 1);
0164 op_metrics->om_timeouts += task->tk_timeouts;
0165
0166 op_metrics->om_bytes_sent += req->rq_xmit_bytes_sent;
0167 op_metrics->om_bytes_recv += req->rq_reply_bytes_recvd;
0168
0169 backlog = 0;
0170 if (ktime_to_ns(req->rq_xtime)) {
0171 backlog = ktime_sub(req->rq_xtime, task->tk_start);
0172 op_metrics->om_queue = ktime_add(op_metrics->om_queue, backlog);
0173 }
0174
0175 op_metrics->om_rtt = ktime_add(op_metrics->om_rtt, req->rq_rtt);
0176
0177 execute = ktime_sub(now, task->tk_start);
0178 op_metrics->om_execute = ktime_add(op_metrics->om_execute, execute);
0179 if (task->tk_status < 0)
0180 op_metrics->om_error_status++;
0181
0182 spin_unlock(&op_metrics->om_lock);
0183
0184 trace_rpc_stats_latency(req->rq_task, backlog, req->rq_rtt, execute);
0185 }
0186 EXPORT_SYMBOL_GPL(rpc_count_iostats_metrics);
0187
0188
0189
0190
0191
0192
0193
0194
0195 void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
0196 {
0197 rpc_count_iostats_metrics(task,
0198 &stats[task->tk_msg.rpc_proc->p_statidx]);
0199 }
0200 EXPORT_SYMBOL_GPL(rpc_count_iostats);
0201
0202 static void _print_name(struct seq_file *seq, unsigned int op,
0203 const struct rpc_procinfo *procs)
0204 {
0205 if (procs[op].p_name)
0206 seq_printf(seq, "\t%12s: ", procs[op].p_name);
0207 else if (op == 0)
0208 seq_printf(seq, "\t NULL: ");
0209 else
0210 seq_printf(seq, "\t%12u: ", op);
0211 }
0212
0213 static void _add_rpc_iostats(struct rpc_iostats *a, struct rpc_iostats *b)
0214 {
0215 a->om_ops += b->om_ops;
0216 a->om_ntrans += b->om_ntrans;
0217 a->om_timeouts += b->om_timeouts;
0218 a->om_bytes_sent += b->om_bytes_sent;
0219 a->om_bytes_recv += b->om_bytes_recv;
0220 a->om_queue = ktime_add(a->om_queue, b->om_queue);
0221 a->om_rtt = ktime_add(a->om_rtt, b->om_rtt);
0222 a->om_execute = ktime_add(a->om_execute, b->om_execute);
0223 a->om_error_status += b->om_error_status;
0224 }
0225
0226 static void _print_rpc_iostats(struct seq_file *seq, struct rpc_iostats *stats,
0227 int op, const struct rpc_procinfo *procs)
0228 {
0229 _print_name(seq, op, procs);
0230 seq_printf(seq, "%lu %lu %lu %llu %llu %llu %llu %llu %lu\n",
0231 stats->om_ops,
0232 stats->om_ntrans,
0233 stats->om_timeouts,
0234 stats->om_bytes_sent,
0235 stats->om_bytes_recv,
0236 ktime_to_ms(stats->om_queue),
0237 ktime_to_ms(stats->om_rtt),
0238 ktime_to_ms(stats->om_execute),
0239 stats->om_error_status);
0240 }
0241
0242 static int do_print_stats(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *seqv)
0243 {
0244 struct seq_file *seq = seqv;
0245
0246 xprt->ops->print_stats(xprt, seq);
0247 return 0;
0248 }
0249
0250 void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt)
0251 {
0252 unsigned int op, maxproc = clnt->cl_maxproc;
0253
0254 if (!clnt->cl_metrics)
0255 return;
0256
0257 seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS);
0258 seq_printf(seq, "p/v: %u/%u (%s)\n",
0259 clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name);
0260
0261 rpc_clnt_iterate_for_each_xprt(clnt, do_print_stats, seq);
0262
0263 seq_printf(seq, "\tper-op statistics\n");
0264 for (op = 0; op < maxproc; op++) {
0265 struct rpc_iostats stats = {};
0266 struct rpc_clnt *next = clnt;
0267 do {
0268 _add_rpc_iostats(&stats, &next->cl_metrics[op]);
0269 if (next == next->cl_parent)
0270 break;
0271 next = next->cl_parent;
0272 } while (next);
0273 _print_rpc_iostats(seq, &stats, op, clnt->cl_procinfo);
0274 }
0275 }
0276 EXPORT_SYMBOL_GPL(rpc_clnt_show_stats);
0277
0278
0279
0280
0281 static inline struct proc_dir_entry *
0282 do_register(struct net *net, const char *name, void *data,
0283 const struct proc_ops *proc_ops)
0284 {
0285 struct sunrpc_net *sn;
0286
0287 dprintk("RPC: registering /proc/net/rpc/%s\n", name);
0288 sn = net_generic(net, sunrpc_net_id);
0289 return proc_create_data(name, 0, sn->proc_net_rpc, proc_ops, data);
0290 }
0291
0292 struct proc_dir_entry *
0293 rpc_proc_register(struct net *net, struct rpc_stat *statp)
0294 {
0295 return do_register(net, statp->program->name, statp, &rpc_proc_ops);
0296 }
0297 EXPORT_SYMBOL_GPL(rpc_proc_register);
0298
0299 void
0300 rpc_proc_unregister(struct net *net, const char *name)
0301 {
0302 struct sunrpc_net *sn;
0303
0304 sn = net_generic(net, sunrpc_net_id);
0305 remove_proc_entry(name, sn->proc_net_rpc);
0306 }
0307 EXPORT_SYMBOL_GPL(rpc_proc_unregister);
0308
0309 struct proc_dir_entry *
0310 svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops)
0311 {
0312 return do_register(net, statp->program->pg_name, statp, proc_ops);
0313 }
0314 EXPORT_SYMBOL_GPL(svc_proc_register);
0315
0316 void
0317 svc_proc_unregister(struct net *net, const char *name)
0318 {
0319 struct sunrpc_net *sn;
0320
0321 sn = net_generic(net, sunrpc_net_id);
0322 remove_proc_entry(name, sn->proc_net_rpc);
0323 }
0324 EXPORT_SYMBOL_GPL(svc_proc_unregister);
0325
0326 int rpc_proc_init(struct net *net)
0327 {
0328 struct sunrpc_net *sn;
0329
0330 dprintk("RPC: registering /proc/net/rpc\n");
0331 sn = net_generic(net, sunrpc_net_id);
0332 sn->proc_net_rpc = proc_mkdir("rpc", net->proc_net);
0333 if (sn->proc_net_rpc == NULL)
0334 return -ENOMEM;
0335
0336 return 0;
0337 }
0338
0339 void rpc_proc_exit(struct net *net)
0340 {
0341 dprintk("RPC: unregistering /proc/net/rpc\n");
0342 remove_proc_entry("rpc", net->proc_net);
0343 }