Whamcloud - gitweb
- enable command line flags for lctl
[fs/lustre-release.git] / lustre / 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
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/ioctl.h>
38 #include <sys/stat.h>
39 #include <sys/mman.h>
40 #include <asm/atomic.h>
41 #include <linux/module.h>
42 #include <portals/api-support.h>
43
44 #include "lctl.h"
45
46 /* current debug flag
47  */
48 int lctl_debug;
49
50 static char rawbuf[8192];
51 static char *buf = rawbuf;
52 static int max = 8192;
53 static int g_pfd = -1;
54 static int subsystem_array[1 << 8];
55 static int debug_mask = ~0;
56
57 static const char *portal_debug_subsystems[] =
58         {"undefined", "mdc", "mds", "osc", "ost", "class", "obdfs", "llite",
59          "rpc", "ext2obd", "portals", "socknal", "qswnal", "pinger", "filter",
60          "obdtrace", "echo", "ldlm", "lov", "gmnal", "router", NULL};
61 static const char *portal_debug_masks[] =
62         {"trace", "inode", "super", "ext2", "malloc", "cache", "info", "ioctl",
63          "blocks", "net", "warning", "buffs", "other", "dentry", "portals",
64          "page", "dlmtrace", NULL};
65
66 int debug_setup(int argc, char **argv) {
67         memset(subsystem_array, 1, sizeof(subsystem_array));
68         return 0;
69 }
70
71 static int do_debug_mask(char *name, int enable) {
72         int found = 0, i;
73
74         for (i = 0; portal_debug_subsystems[i] != NULL; i++) {
75                 if (strcasecmp(name, portal_debug_subsystems[i]) == 0 ||
76                     strcasecmp(name, "all_subs") == 0) {
77                         fprintf(stderr, "%s output from subsystem \"%s\"\n",
78                                 enable ? "Enabling" : "Disabling",
79                                 portal_debug_subsystems[i]);
80                         subsystem_array[i] = enable;
81                         found = 1;
82                 }
83         }
84         for (i = 0; portal_debug_masks[i] != NULL; i++) {
85                 if (strcasecmp(name, portal_debug_masks[i]) == 0 ||
86                     strcasecmp(name, "all_types") == 0) {
87                         fprintf(stderr, "%s output of type \"%s\"\n",
88                                 enable ? "Enabling" : "Disabling",
89                                 portal_debug_masks[i]);
90                         if (enable)
91                                 debug_mask |= (1 << i);
92                         else
93                                 debug_mask &= ~(1 << i);
94                         found = 1;
95                 }
96         }
97
98         return found;
99 }
100
101 /* if 'raw' is true, don't strip the debug information from the
102  * front of the lines */
103 static void dump_buffer(FILE *fd, char *buf, int size, int raw) {
104         char *p, *z;
105         unsigned long subsystem, debug, dropped = 0, kept = 0;
106         int max_sub, max_type;
107
108         for (max_sub = 0; portal_debug_subsystems[max_sub] != NULL; max_sub++)
109                 ;
110         for (max_type = 0; portal_debug_masks[max_type] != NULL; max_type++)
111                 ;
112
113         while (size) {
114                 p = memchr(buf, '\n', size);
115                 if (!p)
116                         break;
117                 subsystem = strtoul(buf, &z, 16);
118                 debug = strtoul(z + 1, &z, 16);
119
120                 z++;
121                 /* for some reason %*s isn't working. */
122                 *p = '\0';
123                 if (subsystem < max_sub &&
124                     subsystem_array[subsystem] &&
125                     (!debug || (debug_mask & debug))) {
126                         if (raw)
127                                 fprintf(fd, "%s\n", buf);
128                         else
129                                 fprintf(fd, "%s\n", z);
130                         //printf("%s\n", buf);
131                         kept++;
132                 } else {
133                         //fprintf(stderr, "dropping line (%lx:%lx): %s\n", subsystem, debug, buf);
134                         dropped++;
135                 }
136                 *p = '\n';
137                 p++;
138                 size -= (p - buf);
139                 buf = p;
140         }
141
142         fprintf(stderr, "Debug log: %lu lines, %lu kept, %lu dropped.\n",
143                 dropped + kept, kept, dropped);
144 }
145
146 int jt_debug_kernel(int argc, char **argv) {
147         int rc, raw = 0;
148         FILE *fd = stdout;
149         const int databuf_size = (6 << 20);
150         struct portal_ioctl_data data, *newdata;
151         char *databuf = NULL;
152
153         PORTALS_CONNECT;
154
155         if (argc > 3)
156                 return CMD_HELP;
157
158         if (argc > 1) {
159                 fd = fopen(argv[1], "w");
160                 if (fd == NULL) {
161                         fprintf(stderr, "fopen(%s) failed: %s\n", argv[1],
162                                 strerror(errno));
163                         return -1;
164                 }
165         }
166         if (argc > 2)
167                 raw = atoi(argv[2]);
168
169         databuf = malloc(databuf_size);
170         if (!databuf) {
171                 fprintf(stderr, "No memory for buffer.\n");
172                 goto out;
173         }
174
175         memset(&data, 0, sizeof(data));
176         data.ioc_plen1 = databuf_size;
177         data.ioc_pbuf1 = databuf;
178
179         if (portal_ioctl_pack(&data, &buf, max) != 0) {
180                 fprintf(stderr, "portal_ioctl_pack failed.\n");
181                 goto out;
182         }
183
184         rc = ioctl(g_pfd, IOC_PORTAL_GET_DEBUG, buf);
185         if (rc) {
186                 fprintf(stderr, "IOC_PORTAL_GET_DEBUG failed: %s\n",
187                         strerror(errno));
188                 goto out;
189         }
190
191         newdata = (struct portal_ioctl_data *)buf;
192         if (newdata->ioc_size > 0)
193                 dump_buffer(fd, databuf, newdata->ioc_size, raw);
194         else
195                 fprintf(stderr, "No data in the debug buffer.\n");
196
197 out:
198         if (databuf)
199                 free(databuf);
200         if (fd != stdout)
201                 fclose(fd);
202         return 0;
203 }
204
205 int jt_debug_file(int argc, char **argv) {
206         int rc, fd = -1, raw = 0;
207         FILE *output = stdout;
208         char *databuf = NULL;
209         struct stat statbuf;
210
211         if (argc > 4 || argc < 2)
212                 return CMD_HELP;
213
214         fd = open(argv[1], O_RDONLY);
215         if (fd < 0) {
216                 fprintf(stderr, "fopen(%s) failed: %s\n", argv[1],
217                         strerror(errno));
218                 return -1;
219         }
220         rc = fstat(fd, &statbuf);
221         if (rc < 0) {
222                 fprintf(stderr, "fstat failed: %s\n", strerror(errno));
223                 goto out;
224         }
225
226         if (argc == 3) {
227                 output = fopen(argv[2], "w");
228                 if (output == NULL) {
229                         fprintf(stderr, "fopen(%s) failed: %s\n", argv[2],
230                                 strerror(errno));
231                         goto out;
232                 }
233         }
234
235         if (argc == 4)
236                 raw = atoi(argv[3]);
237
238         databuf = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE,
239                        MAP_PRIVATE, fd, 0);
240         if (databuf == NULL) {
241                 fprintf(stderr, "mmap failed: %s\n", strerror(errno));
242                 goto out;
243         }
244
245         dump_buffer(output, databuf, statbuf.st_size, raw);
246
247 out:
248         if (databuf)
249                 munmap(databuf, statbuf.st_size);
250         if (output != stdout)
251                 fclose(output);
252         if (fd > 0)
253                 close(fd);
254         return 0;
255 }
256
257 int jt_debug_clear(int argc, char **argv) {
258         int rc;
259         struct portal_ioctl_data data;
260
261         PORTALS_CONNECT;
262         if (argc != 1)
263                 return CMD_HELP;
264
265         memset(&data, 0, sizeof(data));
266         if (portal_ioctl_pack(&data, &buf, max) != 0) {
267                 fprintf(stderr, "portal_ioctl_pack failed.\n");
268                 return -1;
269         }
270
271         rc = ioctl(g_pfd, IOC_PORTAL_CLEAR_DEBUG, buf);
272         if (rc) {
273                 fprintf(stderr, "IOC_PORTAL_CLEAR_DEBUG failed: %s\n",
274                         strerror(errno));
275                 return -1;
276         }
277         return 0;
278 }
279
280 int jt_debug_mark(int argc, char **argv) {
281         int rc;
282         struct portal_ioctl_data data;
283         char *text;
284         time_t now = time(NULL);
285
286         PORTALS_CONNECT;
287         if (argc > 2)
288                 return CMD_HELP;
289
290         if (argc == 2) {
291                 text = argv[1];
292         } else {
293                 text = ctime(&now);
294                 text[strlen(text) - 1] = '\0'; /* stupid \n */
295         }
296
297         memset(&data, 0, sizeof(data));
298         data.ioc_inllen1 = strlen(text) + 1;
299         data.ioc_inlbuf1 = text;
300         if (portal_ioctl_pack(&data, &buf, max) != 0) {
301                 fprintf(stderr, "portal_ioctl_pack failed.\n");
302                 return -1;
303         }
304
305         rc = ioctl(g_pfd, IOC_PORTAL_MARK_DEBUG, buf);
306         if (rc) {
307                 fprintf(stderr, "IOC_PORTAL_MARK_DEBUG failed: %s\n",
308                         strerror(errno));
309                 return -1;
310         }
311         return 0;
312 }
313
314 int jt_debug_filter(int argc, char **argv) {
315         int   i;
316         
317         if (argc < 2) 
318                 return CMD_HELP;
319
320         for (i = 1; i < argc; i++)
321                 if (!do_debug_mask(argv[i], 0))
322                         fprintf(stderr, "Unknown subsystem or "
323                                 "debug type: %s\n", argv[i]);
324         return 0;
325 }
326
327 int jt_debug_show(int argc, char **argv) {
328         int i;
329         
330         if (argc < 2)
331                 return CMD_HELP;
332
333         for (i = 1; i < argc; i++)
334                 if (!do_debug_mask(argv[i], 1))
335                         fprintf(stderr, "Unknown subsystem or "
336                                 "debug type: %s\n", argv[i]);
337
338         return 0;
339 }
340
341 int jt_debug_list(int argc, char **argv) {
342         int i;
343
344         if (argc != 2)
345                 return CMD_HELP; 
346
347         if (strcasecmp(argv[1], "subs") == 0) {
348                 printf("Subsystems: all_subs");
349                 for (i = 0; portal_debug_subsystems[i] != NULL; i++)
350                         printf(", %s", portal_debug_subsystems[i]);
351                 printf("\n");
352         } else if (strcasecmp(argv[1], "types") == 0) {
353                 printf("Types: all_types");
354                 for (i = 0; portal_debug_masks[i] != NULL; i++)
355                         printf(", %s", portal_debug_masks[i]);
356                 printf("\n");
357         }
358         return 0;
359 }
360
361 int jt_debug_modules(int argc, char **argv) {
362         char *modules[] = {"portals", "ksocknal", "obdclass", "ptlrpc",
363                            "obdext2", "ost", "osc", "mds", "mdc", "llite",
364                            "obdecho", "ldlm", "obdfilter", "extN", "lov",
365                            "mds_ext2", "mds_ext3", "mds_extN", NULL};
366         char *paths[] = {"portals/linux/oslib", "portals/linux/socknal",
367                          "lustre/obdclass", "lustre/ptlrpc", "lustre/obdext2",
368                          "lustre/ost", "lustre/osc", "lustre/mds", "lustre/mdc",
369                          "lustre/llite", "lustre/obdecho", "lustre/ldlm",
370                          "lustre/obdfilter", "lustre/extN", "lustre/lov",
371                          "lustre/mds", "lustre/mds", "lustre/mds", NULL};
372         char *path = "..";
373         char *kernel = "linux";
374         int i;
375
376         if (argc >= 2)
377                 path = argv[1];
378         if (argc == 3) 
379                 kernel = argv[2];
380         if (argc > 3) {
381                 printf("%s [path] [kernel]\n", argv[0]);
382                 return 0;
383         }
384
385         printf("set height 1000\n"
386                "symbol-file\n"
387                "delete\n"
388                "symbol-file %s\n"
389                "b panic\n"
390                "b stop\n", kernel); 
391
392         for (i = 0; modules[i] != NULL; i++) {
393                 struct module_info info;
394                 int rc;
395                 size_t crap;
396                 int query_module(const char *name, int which, void *buf,
397                                  size_t bufsize, size_t *ret);
398
399                 rc = query_module(modules[i], QM_INFO, &info, sizeof(info),
400                                   &crap);
401                 if (rc < 0) {
402                         if (errno != ENOENT)
403                                 printf("query_module(%s) failed: %s\n",
404                                        modules[i], strerror(errno));
405                 } else {
406                         printf("add-symbol-file %s/%s/%s.o 0x%0lx\n", path,
407                                paths[i], modules[i],
408                                info.addr + sizeof(struct module));
409                 }
410         }
411         printf("set height 24\n");
412
413         return 0;
414 }
415
416 int jt_debug_panic(int argc, char **argv) {
417         int rc;
418         struct portal_ioctl_data data;
419
420         PORTALS_CONNECT;
421         if (argc != 1)
422                 return CMD_HELP;
423
424         memset(&data, 0, sizeof(data));
425         if (portal_ioctl_pack(&data, &buf, max) != 0) {
426                 fprintf(stderr, "portal_ioctl_pack failed.\n");
427                 return -1;
428         }
429
430         rc = ioctl(g_pfd, IOC_PORTAL_PANIC, buf);
431         if (rc) {
432                 fprintf(stderr, "IOC_PORTAL_PANIC failed: %s\n",
433                         strerror(errno));
434                 return -1;
435         }
436         return 0;
437 }
438
439 int jt_debug_lctl(int argc, char **argv) {
440         if (argc == 2) {
441                 lctl_debug = strtoul(argv[1], NULL, 0);
442         } else
443                 printf("current lctl_debug: 0x%x\n", lctl_debug);
444         return 0;
445 }