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