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