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>
25 #include <nfs/debug.h>
28 static int verbose = 0;
32 static void find_offset(char *module);
33 static unsigned int find_flag(char **module, char *name);
34 static unsigned int get_flags(void);
35 static void set_flags(unsigned int value);
36 static void print_flags(char *module, unsigned int flags);
37 static void usage(int excode);
40 main(int argc, char **argv)
44 unsigned int flags = 0, oflags;
48 while ((c = getopt(argc, argv, "chm:sv")) != EOF) {
65 fprintf(stderr, "rpcdebug: unknown option -%c\n",
71 if (opt_c + opt_s > 1) {
72 fprintf(stderr, "You can use at most one of -c and -s\n");
77 flags = ~(unsigned int) 0;
79 for (; optind < argc; optind++) {
82 if (!(temp = find_flag(&module, argv[optind]))) {
83 fprintf(stderr, "rpcdebug: unknown flag %s\n",
92 fprintf(stderr, "rpcdebug: no module name specified, and "
93 "could not be inferred.\n");
97 if ((memfd = open("/dev/kmem", O_RDWR)) < 0) {
98 perror("can't open /dev/mem");
104 oflags = get_flags();
107 set_flags(oflags & ~flags);
109 set_flags(oflags | flags);
111 print_flags(module, oflags);
118 #define FLAG(mname, fname) \
119 { #mname, #fname, mname##DBG_##fname }
121 static struct flagmap {
140 /* currently handled by RPCDBG_NFS */
150 FLAG(NFSD, REPCACHE),
169 find_flag(char **module, char *name)
172 unsigned int value = 0;
175 for (i = 0; flagmap[i].module; i++) {
176 if ((mod && strcasecmp(mod, flagmap[i].module))
177 || strcasecmp(name, flagmap[i].name))
181 "rpcdebug: ambiguous symbol name %s.\n"
182 "This name is used by more than one module, "
183 "please specify the module name using\n"
188 value = flagmap[i].value;
191 mod = flagmap[i].module;
204 if (lseek(memfd, flagpos, SEEK_SET) < 0) {
208 if ((count = read(memfd, &value, sizeof(value))) < 0) {
212 if (count != sizeof(value)) {
213 fprintf(stderr, "read failed (only %d bytes read)\n",
218 printf("getting flags 0x%x\n", value);
223 set_flags(unsigned int value)
228 printf("setting flags 0x%x\n", value);
229 if (lseek(memfd, flagpos, SEEK_SET) < 0) {
233 if ((count = write(memfd, &value, sizeof(value))) < 0) {
237 if (count != sizeof(value)) {
238 fprintf(stderr, "write failed (only %d bytes written)\n",
245 find_offset(char *module)
247 char buffer[512], *sp;
252 len = sprintf(symbol, "%s_debug", module);
254 if ((fp = fopen("/proc/ksyms", "r")) < 0) {
255 perror("rpcdebug: can't open /proc/ksyms");
259 while (fgets(buffer, sizeof(buffer), fp) != NULL) {
260 if (!(sp = strchr(buffer, ' ')))
262 if (strncmp(++sp, symbol, len))
264 if (sp[len] != '\n' && sp[len] != '\t'
265 && strncmp(sp+len, "_R", 2))
267 flagpos = (unsigned long) strtol(buffer, &sp, 16);
268 /* printf("position is %lx\n", flagpos); */
269 if (sp && *sp == ' ')
271 fprintf(stderr, "rpcdebug: weird line in /proc/ksyms: %s\n",
276 fprintf(stderr, "rpcdebug: debug symbol for module %s not found.\n",
282 strtolower(char *str)
284 static char temp[64];
288 for (sp = temp; *sp; sp++)
294 print_flags(char *module, unsigned int flags)
296 char *lastmod = NULL;
300 printf("%-10s", strtolower(module));
302 printf("<no flags set>\n");
305 /* printf(" <%x>", flags); */
308 for (i = 0; flagmap[i].module; i++) {
310 if (strcasecmp(flagmap[i].module, module))
312 } else if (!lastmod || strcmp(lastmod, flagmap[i].module)) {
315 printf("%-10s", strtolower(flagmap[i].module));
316 lastmod = flagmap[i].module;
318 if (!(flags & flagmap[i].value)
319 || (module && !strcasecmp(flagmap[i].name, "all")))
321 printf(" %s", strtolower(flagmap[i].name));
329 fprintf(stderr, "usage: rpcdebug [-m module] [-cs] flags ...\n");
331 printf("\nModule Valid flags\n");
332 print_flags(NULL, ~(unsigned int) 0);