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