]> git.decadent.org.uk Git - nfs-utils.git/blob - tools/rpcdebug/rpcdebug.c
Imported upstream 1.2.6
[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,       BIND),
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,       CLIENT),
169         FLAG(NFS,       MOUNT),
170         FLAG(NFS,       FSCACHE),
171         FLAG(NFS,       PNFS),
172         FLAG(NFS,       PNFS_LD),
173         FLAG(NFS,       ALL),
174
175         /* nfsd */
176         FLAG(NFSD,      SOCK),
177         FLAG(NFSD,      FH),
178         FLAG(NFSD,      EXPORT),
179         FLAG(NFSD,      SVC),
180         FLAG(NFSD,      PROC),
181         FLAG(NFSD,      FILEOP),
182         FLAG(NFSD,      AUTH),
183         FLAG(NFSD,      REPCACHE),
184         FLAG(NFSD,      XDR),
185         FLAG(NFSD,      LOCKD),
186         FLAG(NFSD,      ALL),
187
188         /* lockd */
189         FLAG(NLM,       SVC),
190         FLAG(NLM,       CLIENT),
191         FLAG(NLM,       CLNTLOCK),
192         FLAG(NLM,       SVCLOCK),
193         FLAG(NLM,       MONITOR),
194         FLAG(NLM,       CLNTSUBS),
195         FLAG(NLM,       SVCSUBS),
196         FLAG(NLM,       HOSTCACHE),
197         FLAG(NLM,       XDR),
198         FLAG(NLM,       ALL),
199
200       { NULL,           NULL,           0 }
201 };
202
203 static unsigned int
204 find_flag(char **module, char *name)
205 {
206         char            *mod = *module;
207         unsigned int    value = 0;
208         int             i;
209
210         for (i = 0; flagmap[i].module; i++) {
211                 if ((mod && strcasecmp(mod, flagmap[i].module))
212                  || strcasecmp(name, flagmap[i].name))
213                         continue;
214                 if (value) {
215                         fprintf(stderr,
216                                 "%s: ambiguous symbol name %s.\n"
217                                 "This name is used by more than one module, "
218                                 "please specify the module name using\n"
219                                 "the -m option.\n",
220                                 cdename, name);
221                         exit(1);
222                 }
223                 value = flagmap[i].value;
224                 if (*module)
225                         return value;
226                 mod = flagmap[i].module;
227         }
228
229         if (!value) {
230                 if (*module)
231                         fprintf(stderr,
232                                 "%s: unknown module or flag %s/%s\n",
233                                 cdename, *module, name);
234                 else
235                         fprintf(stderr,
236                                 "%s: unknown flag %s\n",
237                                 cdename, name);
238                 exit(1);
239         }
240
241         *module = mod;
242         return value;
243 }
244
245 static unsigned int
246 get_flags(char *module)
247 {
248         char    buffer[256], filename[256];
249         int     sysfd, len;
250
251         snprintf(filename, 256, "/proc/sys/sunrpc/%s_debug", module);
252
253         if ((sysfd = open(filename, O_RDONLY)) < 0) {
254                 perror(filename);
255                 exit(1);
256         }
257         if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) {
258                 perror("read");
259                 exit(1);
260         }
261         close(sysfd);
262         buffer[len - 1] = '\0';
263
264         return strtoul(buffer, NULL, 0);
265 }
266
267 static unsigned int
268 set_flags(char *module, unsigned int value)
269 {
270         char    buffer[64], filename[256];
271         int     sysfd, len, ret;
272
273         snprintf(filename, 256, "/proc/sys/sunrpc/%s_debug", module);
274
275         len = sprintf(buffer, "%d", value);
276         if ((sysfd = open(filename, O_WRONLY)) < 0) {
277                 perror(filename);
278                 exit(1);
279         }
280         if ((ret = write(sysfd, buffer, len)) < 0) {
281                 perror("write");
282                 exit(1);
283         }
284         if (ret < len) {
285                 fprintf(stderr, "error: short write in set_flags!\n");
286                 exit(1);
287         }
288         close(sysfd);
289         return value;
290 }
291
292
293 static char *
294 strtolower(char *str)
295 {
296         static char     temp[64];
297         char            *sp;
298
299         strcpy(temp, str);
300         for (sp = temp; *sp; sp++)
301                 *sp = tolower(*sp);
302         return temp;
303 }
304
305 static void
306 print_flags(FILE *ofp, char *module, unsigned int flags, int show_all)
307 {
308         char            *lastmod = NULL;
309         unsigned int    shown = 0;
310         int             i;
311
312         if (module) {
313                 fprintf(ofp, "%-10s", strtolower(module));
314                 if (!flags) {
315                         fprintf(ofp, "<no flags set>\n");
316                         return;
317                 }
318         }
319
320         for (i = 0, shown = 0; flagmap[i].module; i++) {
321                 if (module) {
322                         if (strcasecmp(flagmap[i].module, module))
323                                 continue;
324                 } else if (!lastmod || strcmp(lastmod, flagmap[i].module)) {
325                         if (lastmod) {
326                                 fprintf(ofp, "\n");
327                                 shown = 0;
328                         }
329                         fprintf(ofp, "%-10s", strtolower(flagmap[i].module));
330                         lastmod = flagmap[i].module;
331                 }
332                 if (!(flags & flagmap[i].value)
333                  || (!show_all && (shown & flagmap[i].value))
334                  || (module && !strcasecmp(flagmap[i].name, "all")))
335                         continue;
336                 fprintf(ofp, " %s", strtolower(flagmap[i].name));
337                 shown |= flagmap[i].value;
338         }
339         fprintf(ofp, "\n");
340 }
341
342 static void
343 usage(int excode, char *module)
344 {
345         if (module)
346           fprintf(stderr, "usage: %s [-v] [-h] [-s flags...|-c flags...]\n", cdename);
347         else
348           fprintf(stderr, "usage: %s [-v] [-h] [-m module] [-s flags...|-c flags...]\n", cdename);
349         fprintf(stderr, "       set or cancel debug flags.\n");
350         if (verbose) {
351           fprintf(stderr, "\nModule     Valid flags\n");
352           print_flags(stderr, module, ~(unsigned int) 0, 1);
353         } else {
354           if (module)
355             fprintf(stderr, "       (use %s -vh to get a list of valid flags)\n", cdename);
356           else
357             fprintf(stderr, "       (use %s -vh to get a list of modules and valid flags)\n", cdename);
358         }
359         exit (excode);
360 }
361