]> git.decadent.org.uk Git - nfs-utils.git/blob - tools/rpcdebug/rpcdebug.c
Merge commit 'debian/1.0.7-2'
[nfs-utils.git] / tools / rpcdebug / rpcdebug.c
1 /*
2  * Get or set RPC debug flags.
3  *
4  * I would have loved to write this without recourse to the sysctl
5  * interface, but the only plausible approach (reading and writing
6  * /dev/kmem at the offsets indicated by the _debug symbols from
7  * /proc/ksyms) didn't work, because /dev/kmem doesn't translate virtual
8  * addresses on write. Unfortunately, modules are stuffed into memory
9  * allocated via vmalloc.
10  *
11  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
12  *           (C) 2004 <frederic.jolly@bull.ext.net>
13  *
14  * 06/15/2004: updated for NFSv4
15  *
16  */
17
18 #include "config.h"
19
20 #include <sys/types.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <getopt.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <ctype.h>
28 /* RPC debug flags
29    #include <sunrpc/debug.h> */
30 /* NFS debug flags
31    #include <nfs_fs.h> */
32 /* NFSD and NLM debug flags
33    #include <nfsd/debug.h> */
34 #include <nfs/debug.h>
35
36 static int              verbose = 0;
37 static char*            cdename;
38
39 static unsigned int     find_flag(char **module, char *name);
40 static unsigned int     get_flags(char *);
41 static unsigned int     set_flags(char *, unsigned int value);
42 static void             print_flags(FILE *, char *, unsigned int, int);
43 static char *           strtolower(char *str);
44 static void             usage(int excode, char *module);
45
46 int
47 main(int argc, char **argv)
48 {
49         int             opt_s = 0,
50                         opt_c = 0;
51         unsigned int    flags = 0, oflags;
52         char *          module = NULL;
53         int             c;
54
55         cdename = malloc(strlen(basename(argv[0])));
56         if (cdename == NULL) {
57           fprintf(stderr, "failed in malloc\n");
58           exit(1);
59         }
60         strcpy(cdename, basename(argv[0]));
61
62         if (!strcmp(cdename, "nfsdebug")) {
63           module = "nfs";
64         }
65         else if (!strcmp(cdename, "nfsddebug")) {
66           module = "nfsd";
67         }
68
69         while ((c = getopt(argc, argv, "chm:sv")) != EOF) {
70                 switch (c) {
71                 case 'c':
72                         opt_c = 1;
73                         break;
74                 case 'h':
75                         usage(0, module);
76                 case 'm':
77                         module = optarg;
78                         break;
79                 case 's':
80                         opt_s = 1;
81                         break;
82                 case 'v':
83                         verbose++;
84                         break;
85                 default:
86                         fprintf(stderr, "%s: unknown option -%c\n", cdename, optopt);
87                         usage(1, module);
88                 }
89         }
90
91         if (opt_c + opt_s > 1) {
92                 fprintf(stderr, "You can use at most one of -c and -s\n");
93                 usage(1, module);
94         }
95
96         if (!module) {
97                 fprintf(stderr, "%s: no module name specified.\n", cdename);
98                 usage(1, module);
99         }
100
101         if (strcmp(module, "nfsd") &&
102             strcmp(module, "nfs") &&
103             strcmp(module, "nlm") &&
104             strcmp(module, "rpc")) {
105                 fprintf(stderr, "%s: unknown module: %s\n", cdename, module);
106                 usage(1, module);
107         }
108
109         if (argc == optind) {
110                 flags = ~(unsigned int) 0;
111         } else {
112                 for (; optind < argc; optind++)
113                         flags |= find_flag(&module, argv[optind]);
114                 if (flags && !opt_c)
115                         opt_s = 1;
116         }
117
118         oflags = get_flags(module);
119
120         if (opt_c) {
121                 oflags = set_flags(module, oflags & ~flags);
122         } else if (opt_s) {
123                 oflags = set_flags(module, oflags | flags);
124         }
125         print_flags(stdout, module, oflags, 0);
126         if (verbose) {
127                 fprintf(stdout, "\nModule     Valid flags\n");
128                 print_flags(stdout, module, ~(unsigned int) 0, 1);
129         }
130
131         return 0;
132 }
133
134 #define FLAG(mname, fname)      \
135       { #mname, #fname, mname##DBG_##fname }
136
137 static struct flagmap {
138         char *          module;
139         char *          name;
140         unsigned int    value;
141 }                       flagmap[] = {
142         /* rpc */
143         FLAG(RPC,       XPRT),
144         FLAG(RPC,       CALL),
145         FLAG(RPC,       DEBUG),
146         FLAG(RPC,       NFS),
147         FLAG(RPC,       AUTH),
148         FLAG(RPC,       PMAP),
149         FLAG(RPC,       SCHED),
150         FLAG(RPC,       SVCSOCK),
151         FLAG(RPC,       SVCDSP),
152         FLAG(RPC,       MISC),
153         FLAG(RPC,       ALL),
154
155         /* nfs */
156         FLAG(NFS,       VFS),
157         FLAG(NFS,       DIRCACHE),
158         FLAG(NFS,       LOOKUPCACHE),
159         FLAG(NFS,       PAGECACHE),
160         FLAG(NFS,       PROC),
161         FLAG(NFS,       XDR),
162         FLAG(NFS,       FILE),
163         FLAG(NFS,       ROOT),
164         //      FLAG(NFS,       CALLBACK),
165         FLAG(NFS,       ALL),
166
167         /* nfsd */
168         FLAG(NFSD,      SOCK),
169         FLAG(NFSD,      FH),
170         FLAG(NFSD,      EXPORT),
171         FLAG(NFSD,      SVC),
172         FLAG(NFSD,      PROC),
173         FLAG(NFSD,      FILEOP),
174         FLAG(NFSD,      AUTH),
175         FLAG(NFSD,      REPCACHE),
176         FLAG(NFSD,      XDR),
177         FLAG(NFSD,      LOCKD),
178         FLAG(NFSD,      ALL),
179
180         /* lockd */
181         FLAG(NLM,       SVC),
182         FLAG(NLM,       CLIENT),
183         FLAG(NLM,       CLNTLOCK),
184         FLAG(NLM,       SVCLOCK),
185         FLAG(NLM,       MONITOR),
186         FLAG(NLM,       CLNTSUBS),
187         FLAG(NLM,       SVCSUBS),
188         FLAG(NLM,       HOSTCACHE),
189         FLAG(NLM,       ALL),
190
191       { NULL,           NULL,           0 }
192 };
193
194 static unsigned int
195 find_flag(char **module, char *name)
196 {
197         char            *mod = *module;
198         unsigned int    value = 0;
199         int             i;
200
201         for (i = 0; flagmap[i].module; i++) {
202                 if ((mod && strcasecmp(mod, flagmap[i].module))
203                  || strcasecmp(name, flagmap[i].name))
204                         continue;
205                 if (value) {
206                         fprintf(stderr,
207                                 "%s: ambiguous symbol name %s.\n"
208                                 "This name is used by more than one module, "
209                                 "please specify the module name using\n"
210                                 "the -m option.\n",
211                                 cdename, name);
212                         exit(1);
213                 }
214                 value = flagmap[i].value;
215                 if (*module)
216                         return value;
217                 mod = flagmap[i].module;
218         }
219
220         if (!value) {
221                 if (*module)
222                         fprintf(stderr,
223                                 "%s: unknown module or flag %s/%s\n",
224                                 cdename, *module, name);
225                 else
226                         fprintf(stderr,
227                                 "%s: unknown flag %s\n",
228                                 cdename, name);
229                 exit(1);
230         }
231
232         *module = mod;
233         return value;
234 }
235
236 static unsigned int
237 get_flags(char *module)
238 {
239         char    buffer[256], filename[256];
240         int     sysfd, len;
241
242         snprintf(filename, 256, "/proc/sys/sunrpc/%s_debug", module);
243
244         if ((sysfd = open(filename, O_RDONLY)) < 0) {
245                 perror(filename);
246                 exit(1);
247         }
248         if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) {
249                 perror("read");
250                 exit(1);
251         }
252         close(sysfd);
253         buffer[len - 1] = '\0';
254
255         return strtoul(buffer, NULL, 0);
256 }
257
258 static unsigned int
259 set_flags(char *module, unsigned int value)
260 {
261         char    buffer[64], filename[256];
262         int     sysfd, len, ret;
263
264         snprintf(filename, 256, "/proc/sys/sunrpc/%s_debug", module);
265
266         len = sprintf(buffer, "%d", value);
267         if ((sysfd = open(filename, O_WRONLY)) < 0) {
268                 perror(filename);
269                 exit(1);
270         }
271         if ((ret = write(sysfd, buffer, len)) < 0) {
272                 perror("write");
273                 exit(1);
274         }
275         if (ret < len) {
276                 fprintf(stderr, "error: short write in set_flags!\n");
277                 exit(1);
278         }
279         close(sysfd);
280         return value;
281 }
282
283
284 static char *
285 strtolower(char *str)
286 {
287         static char     temp[64];
288         char            *sp;
289
290         strcpy(temp, str);
291         for (sp = temp; *sp; sp++)
292                 *sp = tolower(*sp);
293         return temp;
294 }
295
296 static void
297 print_flags(FILE *ofp, char *module, unsigned int flags, int show_all)
298 {
299         char            *lastmod = NULL;
300         unsigned int    shown = 0;
301         int             i;
302
303         if (module) {
304                 fprintf(ofp, "%-10s", strtolower(module));
305                 if (!flags) {
306                         fprintf(ofp, "<no flags set>\n");
307                         return;
308                 }
309         }
310
311         for (i = 0, shown = 0; flagmap[i].module; i++) {
312                 if (module) {
313                         if (strcasecmp(flagmap[i].module, module))
314                                 continue;
315                 } else if (!lastmod || strcmp(lastmod, flagmap[i].module)) {
316                         if (lastmod) {
317                                 fprintf(ofp, "\n");
318                                 shown = 0;
319                         }
320                         fprintf(ofp, "%-10s", strtolower(flagmap[i].module));
321                         lastmod = flagmap[i].module;
322                 }
323                 if (!(flags & flagmap[i].value)
324                  || (!show_all && (shown & flagmap[i].value))
325                  || (module && !strcasecmp(flagmap[i].name, "all")))
326                         continue;
327                 fprintf(ofp, " %s", strtolower(flagmap[i].name));
328                 shown |= flagmap[i].value;
329         }
330         fprintf(ofp, "\n");
331 }
332
333 static void
334 usage(int excode, char *module)
335 {
336         if (module)
337           fprintf(stderr, "usage: %s [-v] [-h] [-s flags...|-c flags...]\n", cdename);
338         else
339           fprintf(stderr, "usage: %s [-v] [-h] [-m module] [-s flags...|-c flags...]\n", cdename);
340         fprintf(stderr, "       set or cancel debug flags.\n");
341         if (verbose) {
342           fprintf(stderr, "\nModule     Valid flags\n");
343           print_flags(stderr, module, ~(unsigned int) 0, 1);
344         } else {
345           if (module)
346             fprintf(stderr, "       (use %s -vh to get a list of valid flags)\n", cdename);
347           else
348             fprintf(stderr, "       (use %s -vh to get a list of modules and valid flags)\n", cdename);
349         }
350         exit (excode);
351 }
352