File: /usr/src/linux/net/sunrpc/stats.c
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 #define __NO_VERSION__
16 #include <linux/module.h>
17
18 #include <linux/kernel.h>
19 #include <linux/sched.h>
20 #include <linux/proc_fs.h>
21 #include <linux/sunrpc/clnt.h>
22 #include <linux/sunrpc/svcsock.h>
23
24 #define RPCDBG_FACILITY RPCDBG_MISC
25
26 static struct proc_dir_entry *proc_net_rpc = NULL;
27
28 /*
29 * Get RPC client stats
30 */
31 int
32 rpc_proc_read(char *buffer, char **start, off_t offset, int count,
33 int *eof, void *data)
34 {
35 struct rpc_stat *statp = (struct rpc_stat *) data;
36 struct rpc_program *prog = statp->program;
37 struct rpc_version *vers;
38 int len, i, j;
39
40 len = sprintf(buffer,
41 "net %d %d %d %d\n",
42 statp->netcnt,
43 statp->netudpcnt,
44 statp->nettcpcnt,
45 statp->nettcpconn);
46 len += sprintf(buffer + len,
47 "rpc %d %d %d\n",
48 statp->rpccnt,
49 statp->rpcretrans,
50 statp->rpcauthrefresh);
51
52 for (i = 0; i < prog->nrvers; i++) {
53 if (!(vers = prog->version[i]))
54 continue;
55 len += sprintf(buffer + len, "proc%d %d",
56 vers->number, vers->nrprocs);
57 for (j = 0; j < vers->nrprocs; j++)
58 len += sprintf(buffer + len, " %d",
59 vers->procs[j].p_count);
60 buffer[len++] = '\n';
61 }
62
63 if (offset >= len) {
64 *start = buffer;
65 *eof = 1;
66 return 0;
67 }
68 *start = buffer + offset;
69 if ((len -= offset) > count)
70 return count;
71 *eof = 1;
72 return len;
73 }
74
75 /*
76 * Get RPC server stats
77 */
78 int
79 svc_proc_read(char *buffer, char **start, off_t offset, int count,
80 int *eof, void *data)
81 {
82 struct svc_stat *statp = (struct svc_stat *) data;
83 struct svc_program *prog = statp->program;
84 struct svc_procedure *proc;
85 struct svc_version *vers;
86 int len, i, j;
87
88 len = sprintf(buffer,
89 "net %d %d %d %d\n",
90 statp->netcnt,
91 statp->netudpcnt,
92 statp->nettcpcnt,
93 statp->nettcpconn);
94 len += sprintf(buffer + len,
95 "rpc %d %d %d %d %d\n",
96 statp->rpccnt,
97 statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
98 statp->rpcbadfmt,
99 statp->rpcbadauth,
100 statp->rpcbadclnt);
101
102 for (i = 0; i < prog->pg_nvers; i++) {
103 if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc))
104 continue;
105 len += sprintf(buffer + len, "proc%d %d", i, vers->vs_nproc);
106 for (j = 0; j < vers->vs_nproc; j++, proc++)
107 len += sprintf(buffer + len, " %d", proc->pc_count);
108 buffer[len++] = '\n';
109 }
110
111 if (offset >= len) {
112 *start = buffer;
113 *eof = 1;
114 return 0;
115 }
116 *start = buffer + offset;
117 if ((len -= offset) > count)
118 return count;
119 *eof = 1;
120 return len;
121 }
122
123 /*
124 * Register/unregister RPC proc files
125 */
126 static inline struct proc_dir_entry *
127 do_register(const char *name, void *data, int issvc)
128 {
129 rpc_proc_init();
130 dprintk("RPC: registering /proc/net/rpc/%s\n", name);
131 return create_proc_read_entry(name, 0, proc_net_rpc,
132 issvc? svc_proc_read : rpc_proc_read,
133 data);
134 }
135
136 struct proc_dir_entry *
137 rpc_proc_register(struct rpc_stat *statp)
138 {
139 return do_register(statp->program->name, statp, 0);
140 }
141
142 void
143 rpc_proc_unregister(const char *name)
144 {
145 remove_proc_entry(name, proc_net_rpc);
146 }
147
148 struct proc_dir_entry *
149 svc_proc_register(struct svc_stat *statp)
150 {
151 return do_register(statp->program->pg_name, statp, 1);
152 }
153
154 void
155 svc_proc_unregister(const char *name)
156 {
157 remove_proc_entry(name, proc_net_rpc);
158 }
159
160 void
161 rpc_proc_init(void)
162 {
163 dprintk("RPC: registering /proc/net/rpc\n");
164 if (!proc_net_rpc) {
165 struct proc_dir_entry *ent;
166 ent = proc_mkdir("net/rpc", 0);
167 if (ent) {
168 ent->owner = THIS_MODULE;
169 proc_net_rpc = ent;
170 }
171 }
172 }
173
174 void
175 rpc_proc_exit(void)
176 {
177 dprintk("RPC: unregistering /proc/net/rpc\n");
178 if (proc_net_rpc) {
179 proc_net_rpc = NULL;
180 remove_proc_entry("net/rpc", 0);
181 }
182 }
183
184 #ifdef MODULE
185
186 int
187 init_module(void)
188 {
189 #ifdef RPC_DEBUG
190 rpc_register_sysctl();
191 #endif
192 rpc_proc_init();
193 return 0;
194 }
195
196 void
197 cleanup_module(void)
198 {
199 #ifdef RPC_DEBUG
200 rpc_unregister_sysctl();
201 #endif
202 rpc_proc_exit();
203 }
204 #endif
205