2 * Get or set RPC debug flags.
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.
11 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
23 #include <nfs/debug.h>
26 static int verbose = 0;
30 static void find_offset(char *module);
31 static unsigned int find_flag(char **module, char *name);
32 static unsigned int get_flags(void);
33 static void set_flags(unsigned int value);
34 static void print_flags(char *module, unsigned int flags);
35 static void usage(int excode);
38 main(int argc, char **argv)
42 unsigned int flags = 0, oflags;
46 while ((c = getopt(argc, argv, "chm:sv")) != EOF) {
63 fprintf(stderr, "rpcdebug: unknown option -%c\n",
69 if (opt_c + opt_s > 1) {
70 fprintf(stderr, "You can use at most one of -c and -s\n");
75 flags = ~(unsigned int) 0;
77 for (; optind < argc; optind++) {
80 if (!(temp = find_flag(&module, argv[optind]))) {
81 fprintf(stderr, "rpcdebug: unknown flag %s\n",
90 fprintf(stderr, "rpcdebug: no module name specified, and "
91 "could not be inferred.\n");
95 if ((memfd = open("/dev/kmem", O_RDWR)) < 0) {
96 perror("can't open /dev/mem");
102 oflags = get_flags();
105 set_flags(oflags & ~flags);
107 set_flags(oflags | flags);
109 print_flags(module, oflags);
116 #define FLAG(mname, fname) \
117 { #mname, #fname, mname##DBG_##fname }
119 static struct flagmap {
138 /* currently handled by RPCDBG_NFS */
148 FLAG(NFSD, REPCACHE),
167 find_flag(char **module, char *name)
170 unsigned int value = 0;
173 for (i = 0; flagmap[i].module; i++) {
174 if ((mod && strcasecmp(mod, flagmap[i].module))
175 || strcasecmp(name, flagmap[i].name))
179 "rpcdebug: ambiguous symbol name %s.\n"
180 "This name is used by more than one module, "
181 "please specify the module name using\n"
186 value = flagmap[i].value;
189 mod = flagmap[i].module;
202 if (lseek(memfd, flagpos, SEEK_SET) < 0) {
206 if ((count = read(memfd, &value, sizeof(value))) < 0) {
210 if (count != sizeof(value)) {
211 fprintf(stderr, "read failed (only %d bytes read)\n",
216 printf("getting flags 0x%x\n", value);
221 set_flags(unsigned int value)
226 printf("setting flags 0x%x\n", value);
227 if (lseek(memfd, flagpos, SEEK_SET) < 0) {
231 if ((count = write(memfd, &value, sizeof(value))) < 0) {
235 if (count != sizeof(value)) {
236 fprintf(stderr, "write failed (only %d bytes written)\n",
243 find_offset(char *module)
245 char buffer[512], *sp;
250 len = sprintf(symbol, "%s_debug", module);
252 if ((fp = fopen("/proc/ksyms", "r")) < 0) {
253 perror("rpcdebug: can't open /proc/ksyms");
257 while (fgets(buffer, sizeof(buffer), fp) != NULL) {
258 if (!(sp = strchr(buffer, ' ')))
260 if (strncmp(++sp, symbol, len))
262 if (sp[len] != '\n' && sp[len] != '\t'
263 && strncmp(sp+len, "_R", 2))
265 flagpos = (unsigned long) strtol(buffer, &sp, 16);
266 /* printf("position is %lx\n", flagpos); */
267 if (sp && *sp == ' ')
269 fprintf(stderr, "rpcdebug: weird line in /proc/ksyms: %s\n",
274 fprintf(stderr, "rpcdebug: debug symbol for module %s not found.\n",
280 strtolower(char *str)
282 static char temp[64];
286 for (sp = temp; *sp; sp++)
292 print_flags(char *module, unsigned int flags)
294 char *lastmod = NULL;
298 printf("%-10s", strtolower(module));
300 printf("<no flags set>\n");
303 /* printf(" <%x>", flags); */
306 for (i = 0; flagmap[i].module; i++) {
308 if (strcasecmp(flagmap[i].module, module))
310 } else if (!lastmod || strcmp(lastmod, flagmap[i].module)) {
313 printf("%-10s", strtolower(flagmap[i].module));
314 lastmod = flagmap[i].module;
316 if (!(flags & flagmap[i].value)
317 || (module && !strcasecmp(flagmap[i].name, "all")))
319 printf(" %s", strtolower(flagmap[i].name));
327 fprintf(stderr, "usage: rpcdebug [-m module] [-cs] flags ...\n");
329 printf("\nModule Valid flags\n");
330 print_flags(NULL, ~(unsigned int) 0);