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