Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[fs/lustre-release.git] / lustre / portals / utils / debug.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of Portals, http://www.sf.net/projects/lustre/
7  *
8  *   Portals is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Portals is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Portals; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * Some day I'll split all of this functionality into a cfs_debug module
22  * of its own.  That day is not today.
23  *
24  */
25
26 #include <stdio.h>
27 #include <netdb.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <time.h>
34 #include <syscall.h>
35
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #define BUG()                            /* workaround for module.h includes */
42 #include <linux/version.h>
43
44 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
45 #include <linux/module.h>
46 #endif
47
48 #include <portals/api-support.h>
49 #include <portals/ptlctl.h>
50 #include "parser.h"
51
52 static char rawbuf[8192];
53 static char *buf = rawbuf;
54 static int max = 8192;
55 //static int g_pfd = -1;
56 static int subsystem_mask = ~0;
57 static int debug_mask = ~0;
58
59 static const char *portal_debug_subsystems[] =
60         {"undefined", "mdc", "mds", "osc", "ost", "class", "log", "llite",
61          "rpc", "mgmt", "portals", "socknal", "qswnal", "pinger", "filter",
62          "ptlbd", "echo", "ldlm", "lov", "gmnal", "router", "cobd", NULL};
63 static const char *portal_debug_masks[] =
64         {"trace", "inode", "super", "ext2", "malloc", "cache", "info", "ioctl",
65          "blocks", "net", "warning", "buffs", "other", "dentry", "portals",
66          "page", "dlmtrace", "error", "emerg", "ha", "rpctrace", "vfstrace",
67          NULL};
68
69 struct debug_daemon_cmd {
70         char *cmd;
71         unsigned int cmdv;
72 };
73
74 static const struct debug_daemon_cmd portal_debug_daemon_cmd[] = {
75         {"start", DEBUG_DAEMON_START},
76         {"stop", DEBUG_DAEMON_STOP},
77         {"pause", DEBUG_DAEMON_PAUSE},
78         {"continue", DEBUG_DAEMON_CONTINUE},
79         {0, 0}
80 };
81
82 static int do_debug_mask(char *name, int enable)
83 {
84         int found = 0, i;
85
86         for (i = 0; portal_debug_subsystems[i] != NULL; i++) {
87                 if (strcasecmp(name, portal_debug_subsystems[i]) == 0 ||
88                     strcasecmp(name, "all_subs") == 0) {
89                         printf("%s output from subsystem \"%s\"\n",
90                                 enable ? "Enabling" : "Disabling",
91                                 portal_debug_subsystems[i]);
92                         if (enable)
93                                 subsystem_mask |= (1 << i);
94                         else
95                                 subsystem_mask &= ~(1 << i);
96                         found = 1;
97                 }
98         }
99         for (i = 0; portal_debug_masks[i] != NULL; i++) {
100                 if (strcasecmp(name, portal_debug_masks[i]) == 0 ||
101                     strcasecmp(name, "all_types") == 0) {
102                         printf("%s output of type \"%s\"\n",
103                                 enable ? "Enabling" : "Disabling",
104                                 portal_debug_masks[i]);
105                         if (enable)
106                                 debug_mask |= (1 << i);
107                         else
108                                 debug_mask &= ~(1 << i);
109                         found = 1;
110                 }
111         }
112
113         return found;
114 }
115
116 int dbg_initialize(int argc, char **argv)
117 {
118         return 0;
119 }
120
121 int jt_dbg_filter(int argc, char **argv)
122 {
123         int   i;
124
125         if (argc < 2) {
126                 fprintf(stderr, "usage: %s <subsystem ID or debug mask>\n",
127                         argv[0]);
128                 return 0;
129         }
130
131         for (i = 1; i < argc; i++)
132                 if (!do_debug_mask(argv[i], 0))
133                         fprintf(stderr, "Unknown subsystem or debug type: %s\n",
134                                 argv[i]);
135         return 0;
136 }
137
138 int jt_dbg_show(int argc, char **argv)
139 {
140         int    i;
141
142         if (argc < 2) {
143                 fprintf(stderr, "usage: %s <subsystem ID or debug mask>\n",
144                         argv[0]);
145                 return 0;
146         }
147
148         for (i = 1; i < argc; i++)
149                 if (!do_debug_mask(argv[i], 1))
150                         fprintf(stderr, "Unknown subsystem or debug type: %s\n",
151                                 argv[i]);
152
153         return 0;
154 }
155
156 static int applymask(char* procpath, int value)
157 {
158         int rc;
159         char buf[64];
160         int len = snprintf(buf, 64, "%d", value);
161
162         int fd = open(procpath, O_WRONLY);
163         if (fd == -1) {
164                 fprintf(stderr, "Unable to open %s: %s\n",
165                         procpath, strerror(errno));
166                 return fd;
167         }
168         rc = write(fd, buf, len+1);
169         if (rc<0) {
170                 fprintf(stderr, "Write to %s failed: %s\n",
171                         procpath, strerror(errno));
172                 return rc;
173         }
174         close(fd);
175         return 0;
176 }
177
178 extern char *dump_filename;
179 extern int dump(int dev_id, int opc, void *buf);
180
181 static void applymask_all(unsigned int subs_mask, unsigned int debug_mask)
182 {
183         if (!dump_filename) {
184                 applymask("/proc/sys/portals/subsystem_debug", subs_mask);
185                 applymask("/proc/sys/portals/debug", debug_mask);
186         } else {
187                 struct portals_debug_ioctl_data data;
188
189                 data.hdr.ioc_len = sizeof(data);
190                 data.hdr.ioc_version = 0;
191                 data.subs = subs_mask;
192                 data.debug = debug_mask;
193
194                 dump(OBD_DEV_ID, PTL_IOC_DEBUG_MASK, &data);
195         }
196         printf("Applied subsystem_debug=%d, debug=%d to /proc/sys/portals\n",
197                subs_mask, debug_mask);
198 }
199
200 int jt_dbg_list(int argc, char **argv)
201 {
202         int i;
203
204         if (argc != 2) {
205                 fprintf(stderr, "usage: %s <subs || types>\n", argv[0]);
206                 return 0;
207         }
208
209         if (strcasecmp(argv[1], "subs") == 0) {
210                 printf("Subsystems: all_subs");
211                 for (i = 0; portal_debug_subsystems[i] != NULL; i++)
212                         printf(", %s", portal_debug_subsystems[i]);
213                 printf("\n");
214         } else if (strcasecmp(argv[1], "types") == 0) {
215                 printf("Types: all_types");
216                 for (i = 0; portal_debug_masks[i] != NULL; i++)
217                         printf(", %s", portal_debug_masks[i]);
218                 printf("\n");
219         } else if (strcasecmp(argv[1], "applymasks") == 0) {
220                 applymask_all(subsystem_mask, debug_mask);
221         }
222         return 0;
223 }
224
225 /* if 'raw' is true, don't strip the debug information from the front of the
226  * lines */
227 static void dump_buffer(FILE *fd, char *buf, int size, int raw)
228 {
229         char *p, *z;
230         unsigned long subsystem, debug, dropped = 0, kept = 0;
231
232         while (size) {
233                 p = memchr(buf, '\n', size);
234                 if (!p)
235                         break;
236                 subsystem = strtoul(buf, &z, 16);
237                 debug = strtoul(z + 1, &z, 16);
238
239                 z++;
240                 /* for some reason %*s isn't working. */
241                 *p = '\0';
242                 if ((subsystem_mask & subsystem) &&
243                     (!debug || (debug_mask & debug))) {
244                         if (raw)
245                                 fprintf(fd, "%s\n", buf);
246                         else
247                                 fprintf(fd, "%s\n", z);
248                         //printf("%s\n", buf);
249                         kept++;
250                 } else {
251                         //fprintf(stderr, "dropping line (%lx:%lx): %s\n", subsystem, debug, buf);
252                         dropped++;
253                 }
254                 *p = '\n';
255                 p++;
256                 size -= (p - buf);
257                 buf = p;
258         }
259
260         printf("Debug log: %lu lines, %lu kept, %lu dropped.\n",
261                 dropped + kept, kept, dropped);
262 }
263
264 int jt_dbg_debug_kernel(int argc, char **argv)
265 {
266         int rc, raw = 1;
267         FILE *fd = stdout;
268         const int databuf_size = (6 << 20);
269         struct portal_ioctl_data data, *newdata;
270         char *databuf = NULL;
271
272         if (argc > 3) {
273                 fprintf(stderr, "usage: %s [file] [raw]\n", argv[0]);
274                 return 0;
275         }
276
277         if (argc > 1) {
278                 fd = fopen(argv[1], "w");
279                 if (fd == NULL) {
280                         fprintf(stderr, "fopen(%s) failed: %s\n", argv[1],
281                                 strerror(errno));
282                         return -1;
283                 }
284         }
285         if (argc > 2)
286                 raw = atoi(argv[2]);
287
288         databuf = malloc(databuf_size);
289         if (!databuf) {
290                 fprintf(stderr, "No memory for buffer.\n");
291                 goto out;
292         }
293
294         memset(&data, 0, sizeof(data));
295         data.ioc_plen1 = databuf_size;
296         data.ioc_pbuf1 = databuf;
297
298         if (portal_ioctl_pack(&data, &buf, max) != 0) {
299                 fprintf(stderr, "portal_ioctl_pack failed.\n");
300                 goto out;
301         }
302
303         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_DEBUG, buf);
304         if (rc) {
305                 fprintf(stderr, "IOC_PORTAL_GET_DEBUG failed: %s\n",
306                         strerror(errno));
307                 goto out;
308         }
309
310         newdata = (struct portal_ioctl_data *)buf;
311         if (newdata->ioc_size > 0)
312                 dump_buffer(fd, databuf, newdata->ioc_size, raw);
313
314  out:
315         if (databuf)
316                 free(databuf);
317         if (fd != stdout)
318                 fclose(fd);
319         return 0;
320 }
321
322 int jt_dbg_debug_daemon(int argc, char **argv)
323 {
324         int i, rc;
325         unsigned int cmd = 0;
326         FILE *fd = stdout;
327         struct portal_ioctl_data data;
328
329         if (argc <= 1) {
330                 fprintf(stderr, "usage: %s [start file <#MB>|stop|pause|"
331                         "continue]\n", argv[0]);
332                 return 0;
333         }
334         for (i = 0; portal_debug_daemon_cmd[i].cmd != NULL; i++) {
335                 if (strcasecmp(argv[1], portal_debug_daemon_cmd[i].cmd) == 0) {
336                         cmd = portal_debug_daemon_cmd[i].cmdv;
337                         break;
338                 }
339         }
340         if (portal_debug_daemon_cmd[i].cmd == NULL) {
341                 fprintf(stderr, "usage: %s [start file <#MB>|stop|pause|"
342                         "continue]\n", argv[0]);
343                 return 0;
344         }
345         memset(&data, 0, sizeof(data));
346         if (cmd == DEBUG_DAEMON_START) {
347                 if (argc < 3) {
348                         fprintf(stderr, "usage: %s [start file <#MB>|stop|"
349                                 "pause|continue]\n", argv[0]);
350                         return 0;
351                 }
352                 if (access(argv[2], F_OK) != 0) {
353                         fd = fopen(argv[2], "w");
354                         if (fd != NULL) {
355                                 fclose(fd);
356                                 remove(argv[2]);
357                                 goto ok;
358                         }
359                 }
360                 if (access(argv[2], W_OK) == 0)
361                         goto ok;
362                 fprintf(stderr, "fopen(%s) failed: %s\n", argv[2],
363                         strerror(errno));
364                 return -1;
365 ok:
366                 data.ioc_inllen1 = strlen(argv[2]) + 1;
367                 data.ioc_inlbuf1 = argv[2];
368                 data.ioc_misc = 0;
369                 if (argc == 4) {
370                         unsigned long size;
371                         errno = 0;
372                         size = strtoul(argv[3], NULL, 0);
373                         if (errno) {
374                                 fprintf(stderr, "file size(%s): error %s\n",
375                                         argv[3], strerror(errno));
376                                 return -1;
377                         }
378                         data.ioc_misc = size;
379                 }
380         }
381         data.ioc_count = cmd;
382         if (portal_ioctl_pack(&data, &buf, max) != 0) {
383                 fprintf(stderr, "portal_ioctl_pack failed.\n");
384                 return -1;
385         }
386         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_SET_DAEMON, buf);
387         if (rc < 0) {
388                 fprintf(stderr, "IOC_PORTAL_SET_DEMON failed: %s\n",
389                                 strerror(errno));
390                 return rc;
391         }
392         return 0;
393 }
394
395 int jt_dbg_debug_file(int argc, char **argv)
396 {
397         int rc, fd = -1, raw = 1;
398         FILE *output = stdout;
399         char *databuf = NULL;
400         struct stat statbuf;
401
402         if (argc > 4 || argc < 2) {
403                 fprintf(stderr, "usage: %s <input> [output] [raw]\n", argv[0]);
404                 return 0;
405         }
406
407         fd = open(argv[1], O_RDONLY);
408         if (fd < 0) {
409                 fprintf(stderr, "fopen(%s) failed: %s\n", argv[1],
410                         strerror(errno));
411                 return -1;
412         }
413 #warning FIXME: cleanup fstat issue here
414 #ifndef SYS_fstat64
415 #define __SYS_fstat__ SYS_fstat
416 #else
417 #define __SYS_fstat__ SYS_fstat64
418 #endif
419         rc = syscall(__SYS_fstat__, fd, &statbuf);
420         if (rc < 0) {
421                 fprintf(stderr, "fstat failed: %s\n", strerror(errno));
422                 goto out;
423         }
424
425         if (argc >= 3) {
426                 output = fopen(argv[2], "w");
427                 if (output == NULL) {
428                         fprintf(stderr, "fopen(%s) failed: %s\n", argv[2],
429                                 strerror(errno));
430                         goto out;
431                 }
432         }
433
434         if (argc == 4)
435                 raw = atoi(argv[3]);
436
437         databuf = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE,
438                        MAP_PRIVATE, fd, 0);
439         if (databuf == NULL) {
440                 fprintf(stderr, "mmap failed: %s\n", strerror(errno));
441                 goto out;
442         }
443
444         dump_buffer(output, databuf, statbuf.st_size, raw);
445
446  out:
447         if (databuf)
448                 munmap(databuf, statbuf.st_size);
449         if (output != stdout)
450                 fclose(output);
451         if (fd > 0)
452                 close(fd);
453         return 0;
454 }
455
456 int jt_dbg_clear_debug_buf(int argc, char **argv)
457 {
458         int rc;
459         struct portal_ioctl_data data;
460
461         if (argc != 1) {
462                 fprintf(stderr, "usage: %s\n", argv[0]);
463                 return 0;
464         }
465
466         memset(&data, 0, sizeof(data));
467         if (portal_ioctl_pack(&data, &buf, max) != 0) {
468                 fprintf(stderr, "portal_ioctl_pack failed.\n");
469                 return -1;
470         }
471
472         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_CLEAR_DEBUG, buf);
473         if (rc) {
474                 fprintf(stderr, "IOC_PORTAL_CLEAR_DEBUG failed: %s\n",
475                         strerror(errno));
476                 return -1;
477         }
478         return 0;
479 }
480
481 int jt_dbg_mark_debug_buf(int argc, char **argv)
482 {
483         int rc;
484         struct portal_ioctl_data data;
485         char *text;
486         time_t now = time(NULL);
487
488         if (argc > 2) {
489                 fprintf(stderr, "usage: %s [marker text]\n", argv[0]);
490                 return 0;
491         }
492
493         if (argc == 2) {
494                 text = argv[1];
495         } else {
496                 text = ctime(&now);
497                 text[strlen(text) - 1] = '\0'; /* stupid \n */
498         }
499
500         memset(&data, 0, sizeof(data));
501         data.ioc_inllen1 = strlen(text) + 1;
502         data.ioc_inlbuf1 = text;
503         if (portal_ioctl_pack(&data, &buf, max) != 0) {
504                 fprintf(stderr, "portal_ioctl_pack failed.\n");
505                 return -1;
506         }
507
508         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_MARK_DEBUG, buf);
509         if (rc) {
510                 fprintf(stderr, "IOC_PORTAL_MARK_DEBUG failed: %s\n",
511                         strerror(errno));
512                 return -1;
513         }
514         return 0;
515 }
516
517
518 int jt_dbg_modules(int argc, char **argv)
519 {
520 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
521         struct mod_paths {
522                 char *name, *path;
523         } *mp, mod_paths[] = {
524                 {"portals", "lustre/portals/libcfs"},
525                 {"ksocknal", "lustre/portals/knals/socknal"},
526                 {"obdclass", "lustre/obdclass"},
527                 {"ptlrpc", "lustre/ptlrpc"},
528                 {"obdext2", "lustre/obdext2"},
529                 {"ost", "lustre/ost"},
530                 {"osc", "lustre/osc"},
531                 {"mds", "lustre/mds"},
532                 {"mdc", "lustre/mdc"},
533                 {"llite", "lustre/llite"},
534                 {"obdecho", "lustre/obdecho"},
535                 {"ldlm", "lustre/ldlm"},
536                 {"obdfilter", "lustre/obdfilter"},
537                 {"extN", "lustre/extN"},
538                 {"lov", "lustre/lov"},
539                 {"fsfilt_ext3", "lustre/obdclass"},
540                 {"fsfilt_extN", "lustre/obdclass"},
541                 {"mds_ext2", "lustre/mds"},
542                 {"mds_ext3", "lustre/mds"},
543                 {"mds_extN", "lustre/mds"},
544                 {"ptlbd", "lustre/ptlbd"},
545                 {"mgmt_svc", "lustre/mgmt"},
546                 {"mgmt_cli", "lustre/mgmt"},
547                 {NULL, NULL}
548         };
549         char *path = "..";
550         char *kernel = "linux";
551
552         if (argc >= 2)
553                 path = argv[1];
554         if (argc == 3)
555                 kernel = argv[2];
556         if (argc > 3) {
557                 printf("%s [path] [kernel]\n", argv[0]);
558                 return 0;
559         }
560
561         for (mp = mod_paths; mp->name != NULL; mp++) {
562                 struct module_info info;
563                 int rc;
564                 size_t crap;
565                 int query_module(const char *name, int which, void *buf,
566                                  size_t bufsize, size_t *ret);
567
568                 rc = query_module(mp->name, QM_INFO, &info, sizeof(info),
569                                   &crap);
570                 if (rc < 0) {
571                         if (errno != ENOENT)
572                                 printf("query_module(%s) failed: %s\n",
573                                        mp->name, strerror(errno));
574                 } else {
575                         printf("add-symbol-file %s/%s/%s.o 0x%0lx\n", path,
576                                mp->path, mp->name,
577                                info.addr + sizeof(struct module));
578                 }
579         }
580
581         return 0;
582 #else
583         printf("jt_dbg_module is not yet implemented for Linux 2.5\n");
584         return 0;
585 #endif /* linux 2.5 */
586 }
587
588 int jt_dbg_panic(int argc, char **argv)
589 {
590         int rc;
591         struct portal_ioctl_data data;
592
593         if (argc != 1) {
594                 fprintf(stderr, "usage: %s\n", argv[0]);
595                 return 0;
596         }
597
598         memset(&data, 0, sizeof(data));
599         if (portal_ioctl_pack(&data, &buf, max) != 0) {
600                 fprintf(stderr, "portal_ioctl_pack failed.\n");
601                 return -1;
602         }
603
604         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_PANIC, buf);
605         if (rc) {
606                 fprintf(stderr, "IOC_PORTAL_PANIC failed: %s\n",
607                         strerror(errno));
608                 return -1;
609         }
610         return 0;
611 }