diff options
Diffstat (limited to 'net/sunrpc/stats.c')
-rw-r--r-- | net/sunrpc/stats.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c new file mode 100644 index 000000000000..9b67dc19944c --- /dev/null +++ b/net/sunrpc/stats.c | |||
@@ -0,0 +1,175 @@ | |||
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/sched.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 | |||
25 | #define RPCDBG_FACILITY RPCDBG_MISC | ||
26 | |||
27 | struct proc_dir_entry *proc_net_rpc = NULL; | ||
28 | |||
29 | /* | ||
30 | * Get RPC client stats | ||
31 | */ | ||
32 | static int rpc_proc_show(struct seq_file *seq, void *v) { | ||
33 | const struct rpc_stat *statp = seq->private; | ||
34 | const struct rpc_program *prog = statp->program; | ||
35 | int i, j; | ||
36 | |||
37 | seq_printf(seq, | ||
38 | "net %d %d %d %d\n", | ||
39 | statp->netcnt, | ||
40 | statp->netudpcnt, | ||
41 | statp->nettcpcnt, | ||
42 | statp->nettcpconn); | ||
43 | seq_printf(seq, | ||
44 | "rpc %d %d %d\n", | ||
45 | statp->rpccnt, | ||
46 | statp->rpcretrans, | ||
47 | statp->rpcauthrefresh); | ||
48 | |||
49 | for (i = 0; i < prog->nrvers; i++) { | ||
50 | const struct rpc_version *vers = prog->version[i]; | ||
51 | if (!vers) | ||
52 | continue; | ||
53 | seq_printf(seq, "proc%d %d", | ||
54 | vers->number, vers->nrprocs); | ||
55 | for (j = 0; j < vers->nrprocs; j++) | ||
56 | seq_printf(seq, " %d", | ||
57 | vers->procs[j].p_count); | ||
58 | seq_putc(seq, '\n'); | ||
59 | } | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int rpc_proc_open(struct inode *inode, struct file *file) | ||
64 | { | ||
65 | return single_open(file, rpc_proc_show, PDE(inode)->data); | ||
66 | } | ||
67 | |||
68 | static struct file_operations rpc_proc_fops = { | ||
69 | .owner = THIS_MODULE, | ||
70 | .open = rpc_proc_open, | ||
71 | .read = seq_read, | ||
72 | .llseek = seq_lseek, | ||
73 | .release = single_release, | ||
74 | }; | ||
75 | |||
76 | /* | ||
77 | * Get RPC server stats | ||
78 | */ | ||
79 | void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) { | ||
80 | const struct svc_program *prog = statp->program; | ||
81 | const struct svc_procedure *proc; | ||
82 | const struct svc_version *vers; | ||
83 | int i, j; | ||
84 | |||
85 | seq_printf(seq, | ||
86 | "net %d %d %d %d\n", | ||
87 | statp->netcnt, | ||
88 | statp->netudpcnt, | ||
89 | statp->nettcpcnt, | ||
90 | statp->nettcpconn); | ||
91 | seq_printf(seq, | ||
92 | "rpc %d %d %d %d %d\n", | ||
93 | statp->rpccnt, | ||
94 | statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt, | ||
95 | statp->rpcbadfmt, | ||
96 | statp->rpcbadauth, | ||
97 | statp->rpcbadclnt); | ||
98 | |||
99 | for (i = 0; i < prog->pg_nvers; i++) { | ||
100 | if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc)) | ||
101 | continue; | ||
102 | seq_printf(seq, "proc%d %d", i, vers->vs_nproc); | ||
103 | for (j = 0; j < vers->vs_nproc; j++, proc++) | ||
104 | seq_printf(seq, " %d", proc->pc_count); | ||
105 | seq_putc(seq, '\n'); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Register/unregister RPC proc files | ||
111 | */ | ||
112 | static inline struct proc_dir_entry * | ||
113 | do_register(const char *name, void *data, struct file_operations *fops) | ||
114 | { | ||
115 | struct proc_dir_entry *ent; | ||
116 | |||
117 | rpc_proc_init(); | ||
118 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); | ||
119 | |||
120 | ent = create_proc_entry(name, 0, proc_net_rpc); | ||
121 | if (ent) { | ||
122 | ent->proc_fops = fops; | ||
123 | ent->data = data; | ||
124 | } | ||
125 | return ent; | ||
126 | } | ||
127 | |||
128 | struct proc_dir_entry * | ||
129 | rpc_proc_register(struct rpc_stat *statp) | ||
130 | { | ||
131 | return do_register(statp->program->name, statp, &rpc_proc_fops); | ||
132 | } | ||
133 | |||
134 | void | ||
135 | rpc_proc_unregister(const char *name) | ||
136 | { | ||
137 | remove_proc_entry(name, proc_net_rpc); | ||
138 | } | ||
139 | |||
140 | struct proc_dir_entry * | ||
141 | svc_proc_register(struct svc_stat *statp, struct file_operations *fops) | ||
142 | { | ||
143 | return do_register(statp->program->pg_name, statp, fops); | ||
144 | } | ||
145 | |||
146 | void | ||
147 | svc_proc_unregister(const char *name) | ||
148 | { | ||
149 | remove_proc_entry(name, proc_net_rpc); | ||
150 | } | ||
151 | |||
152 | void | ||
153 | rpc_proc_init(void) | ||
154 | { | ||
155 | dprintk("RPC: registering /proc/net/rpc\n"); | ||
156 | if (!proc_net_rpc) { | ||
157 | struct proc_dir_entry *ent; | ||
158 | ent = proc_mkdir("rpc", proc_net); | ||
159 | if (ent) { | ||
160 | ent->owner = THIS_MODULE; | ||
161 | proc_net_rpc = ent; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | void | ||
167 | rpc_proc_exit(void) | ||
168 | { | ||
169 | dprintk("RPC: unregistering /proc/net/rpc\n"); | ||
170 | if (proc_net_rpc) { | ||
171 | proc_net_rpc = NULL; | ||
172 | remove_proc_entry("net/rpc", NULL); | ||
173 | } | ||
174 | } | ||
175 | |||