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