Whamcloud - gitweb
aae7e461ee88429f2382bb8276fc7826440e569a
[fs/lustre-release.git] / lnet / utils / debug.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2015, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lnet/utils/debug.c
37  * Some day I'll split all of this functionality into a cfs_debug module
38  * of its own. That day is not today.
39  */
40
41 #define __USE_FILE_OFFSET64
42 #ifndef _GNU_SOURCE
43 #define _GNU_SOURCE
44 #endif
45
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <limits.h>
49 #include <stdarg.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sys/ioctl.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <time.h>
57 #include <unistd.h>
58
59 #include <linux/types.h>
60
61 #include <libcfs/util/ioctl.h>
62 #include <libcfs/user-time.h>
63 #include <libcfs/libcfs_debug.h>
64 #include <lnet/lnetctl.h>
65
66 static char rawbuf[8192];
67 static char *buf = rawbuf;
68 static int max = 8192;
69 /*static int g_pfd = -1;*/
70 static int subsystem_mask = ~0;
71 static int debug_mask = ~0;
72
73 #define MAX_MARK_SIZE 256
74
75 static const char *libcfs_debug_subsystems[] = LIBCFS_DEBUG_SUBSYS_NAMES;
76 static const char *libcfs_debug_masks[] = LIBCFS_DEBUG_MASKS_NAMES;
77
78 #define DAEMON_CTL_NAME         "/proc/sys/lnet/daemon_file"
79 #define SUBSYS_DEBUG_CTL_NAME   "/proc/sys/lnet/subsystem_debug"
80 #define DEBUG_CTL_NAME          "/proc/sys/lnet/debug"
81 #define DUMP_KERNEL_CTL_NAME    "/proc/sys/lnet/dump_kernel"
82
83 static int
84 dbg_open_ctlhandle(const char *str)
85 {
86         int fd;
87         fd = open(str, O_WRONLY);
88         if (fd < 0) {
89                 fprintf(stderr, "open %s failed: %s\n", str,
90                         strerror(errno));
91                 return -1;
92         }
93         return fd;
94 }
95
96 static void
97 dbg_close_ctlhandle(int fd)
98 {
99         close(fd);
100 }
101
102 static int
103 dbg_write_cmd(int fd, char *str, int len)
104 {
105         int rc = write(fd, str, len);
106
107         return (rc == len ? 0 : 1);
108 }
109
110
111 static int do_debug_mask(char *name, int enable)
112 {
113         int found = 0;
114         int i;
115
116         for (i = 0; libcfs_debug_subsystems[i] != NULL; i++) {
117                 if (strcasecmp(name, libcfs_debug_subsystems[i]) == 0 ||
118                     strcasecmp(name, "all_subs") == 0) {
119                         printf("%s output from subsystem \"%s\"\n",
120                                 enable ? "Enabling" : "Disabling",
121                                 libcfs_debug_subsystems[i]);
122                         if (enable)
123                                 subsystem_mask |= (1 << i);
124                         else
125                                 subsystem_mask &= ~(1 << i);
126                         found = 1;
127                 }
128         }
129         for (i = 0; libcfs_debug_masks[i] != NULL; i++) {
130                 if (strcasecmp(name, libcfs_debug_masks[i]) == 0 ||
131                     strcasecmp(name, "all_types") == 0) {
132                         printf("%s output of type \"%s\"\n",
133                                 enable ? "Enabling" : "Disabling",
134                                 libcfs_debug_masks[i]);
135                         if (enable)
136                                 debug_mask |= (1 << i);
137                         else
138                                 debug_mask &= ~(1 << i);
139                         found = 1;
140                 }
141         }
142
143         return found;
144 }
145
146 int dbg_initialize(int argc, char **argv)
147 {
148         return 0;
149 }
150
151 int jt_dbg_filter(int argc, char **argv)
152 {
153         int i;
154
155         if (argc < 2) {
156                 fprintf(stderr, "usage: %s <subsystem ID or debug mask>\n",
157                         argv[0]);
158                 return 0;
159         }
160
161         for (i = 1; i < argc; i++)
162                 if (!do_debug_mask(argv[i], 0))
163                         fprintf(stderr, "Unknown subsystem or debug type: %s\n",
164                                 argv[i]);
165         return 0;
166 }
167
168 int jt_dbg_show(int argc, char **argv)
169 {
170         int i;
171
172         if (argc < 2) {
173                 fprintf(stderr, "usage: %s <subsystem ID or debug mask>\n",
174                         argv[0]);
175                 return 0;
176         }
177
178         for (i = 1; i < argc; i++)
179                 if (!do_debug_mask(argv[i], 1))
180                         fprintf(stderr, "Unknown subsystem or debug type: %s\n",
181                                 argv[i]);
182
183         return 0;
184 }
185
186 static int applymask(char* procpath, int value)
187 {
188         int     rc;
189         char    buf[64];
190         int     len = snprintf(buf, 64, "%d", value);
191
192         int fd = dbg_open_ctlhandle(procpath);
193         if (fd == -1) {
194                 fprintf(stderr, "Unable to open %s: %s\n",
195                         procpath, strerror(errno));
196                 return fd;
197         }
198         rc = dbg_write_cmd(fd, buf, len+1);
199         if (rc != 0) {
200                 fprintf(stderr, "Write to %s failed: %s\n",
201                         procpath, strerror(errno));
202         }
203
204         dbg_close_ctlhandle(fd);
205
206         return rc;
207 }
208
209 static void applymask_all(unsigned int subs_mask, unsigned int debug_mask)
210 {
211         applymask(SUBSYS_DEBUG_CTL_NAME, subs_mask);
212         applymask(DEBUG_CTL_NAME, debug_mask);
213         printf("Applied subsystem_debug=%d, debug=%d to /proc/sys/lnet\n",
214                subs_mask, debug_mask);
215 }
216
217 int jt_dbg_list(int argc, char **argv)
218 {
219         int i;
220
221         if (argc != 2) {
222                 fprintf(stderr, "usage: %s <subs || types>\n", argv[0]);
223                 return 0;
224         }
225
226         if (strcasecmp(argv[1], "subs") == 0) {
227                 printf("Subsystems: all_subs");
228                 for (i = 0; libcfs_debug_subsystems[i] != NULL; i++)
229                         if (libcfs_debug_subsystems[i][0])
230                                 printf(", %s", libcfs_debug_subsystems[i]);
231                 printf("\n");
232         } else if (strcasecmp(argv[1], "types") == 0) {
233                 printf("Types: all_types");
234                 for (i = 0; libcfs_debug_masks[i] != NULL; i++)
235                         printf(", %s", libcfs_debug_masks[i]);
236                 printf("\n");
237         } else if (strcasecmp(argv[1], "applymasks") == 0) {
238                 applymask_all(subsystem_mask, debug_mask);
239         }
240         return 0;
241 }
242
243 /* all strings nul-terminated; only the struct and hdr need to be freed */
244 struct dbg_line {
245         struct ptldebug_header *hdr;
246         char                   *file;
247         char                   *fn;
248         char                   *text;
249 };
250
251 static int cmp_rec(const void *p1, const void *p2)
252 {
253         struct dbg_line *d1 = *(struct dbg_line **)p1;
254         struct dbg_line *d2 = *(struct dbg_line **)p2;
255
256         if (d1->hdr->ph_sec < d2->hdr->ph_sec)
257                 return -1;
258         if (d1->hdr->ph_sec == d2->hdr->ph_sec &&
259             d1->hdr->ph_usec < d2->hdr->ph_usec)
260                 return -1;
261         if (d1->hdr->ph_sec == d2->hdr->ph_sec &&
262             d1->hdr->ph_usec == d2->hdr->ph_usec)
263                 return 0;
264         return 1;
265 }
266
267 static void print_rec(struct dbg_line ***linevp, int used, int fdout)
268 {
269         struct dbg_line **linev = *linevp;
270         int               i;
271
272         qsort(linev, used, sizeof(struct dbg_line *), cmp_rec);
273         for (i = 0; i < used; i++) {
274                 struct dbg_line         *line = linev[i];
275                 struct ptldebug_header  *hdr = line->hdr;
276                 char                     out[4097];
277                 char                    *buf = out;
278                 int                      bytes;
279                 ssize_t                  bytes_written;
280
281                 bytes = snprintf(out, sizeof(out),
282                                 "%08x:%08x:%u.%u%s:%u.%06llu:%u:%u:%u:"
283                                 "(%s:%u:%s()) %s",
284                                 hdr->ph_subsys, hdr->ph_mask,
285                                 hdr->ph_cpu_id, hdr->ph_type,
286                                 hdr->ph_flags & PH_FLAG_FIRST_RECORD ? "F" : "",
287                                 hdr->ph_sec, (unsigned long long)hdr->ph_usec,
288                                 hdr->ph_stack, hdr->ph_pid, hdr->ph_extern_pid,
289                                 line->file, hdr->ph_line_num, line->fn,
290                                 line->text);
291                 while (bytes > 0) {
292                         bytes_written = write(fdout, buf, bytes);
293                         if (bytes_written <= 0)
294                                 break;
295                         bytes -= bytes_written;
296                         buf += bytes_written;
297                 }
298                 free(line->hdr);
299                 free(line);
300         }
301         free(linev);
302         *linevp = NULL;
303 }
304
305 static int add_rec(struct dbg_line *line, struct dbg_line ***linevp, int *lenp,
306                    int used)
307 {
308         struct dbg_line **linev = *linevp;
309
310         if (used == *lenp) {
311                 int nlen = *lenp + 4096;
312                 int nsize = nlen * sizeof(struct dbg_line *);
313
314                 linev = realloc(*linevp, nsize);
315                 if (!linev)
316                         return -ENOMEM;
317
318                 *linevp = linev;
319                 *lenp = nlen;
320         }
321         linev[used] = line;
322
323         return 0;
324 }
325
326 static void dump_hdr(unsigned long long offset, struct ptldebug_header *hdr)
327 {
328         fprintf(stderr, "badly-formed record at offset = %llu\n", offset);
329         fprintf(stderr, "  len = %u\n", hdr->ph_len);
330         fprintf(stderr, "  flags = %x\n", hdr->ph_flags);
331         fprintf(stderr, "  subsystem = %x\n", hdr->ph_subsys);
332         fprintf(stderr, "  mask = %x\n", hdr->ph_mask);
333         fprintf(stderr, "  cpu_id = %u\n", hdr->ph_cpu_id);
334         fprintf(stderr, "  type = %u\n", hdr->ph_type);
335         fprintf(stderr, "  seconds = %u\n", hdr->ph_sec);
336         fprintf(stderr, "  microseconds = %lu\n", (long)hdr->ph_usec);
337         fprintf(stderr, "  stack = %u\n", hdr->ph_stack);
338         fprintf(stderr, "  pid = %u\n", hdr->ph_pid);
339         fprintf(stderr, "  host pid = %u\n", hdr->ph_extern_pid);
340         fprintf(stderr, "  line number = %u\n", hdr->ph_line_num);
341 }
342
343 #define HDR_SIZE sizeof(*hdr)
344
345 static int parse_buffer(int fdin, int fdout)
346 {
347         struct dbg_line         *line;
348         struct ptldebug_header  *hdr;
349         char                     buf[4097];
350         char                    *ptr;
351         unsigned long            dropped = 0;
352         unsigned long            kept = 0;
353         unsigned long            bad = 0;
354         struct dbg_line         **linev = NULL;
355         int                      linev_len = 0;
356         int                      rc;
357
358         hdr = (void *)buf;
359
360         while (1) {
361                 int first_bad = 1;
362                 int count;
363
364                 count = HDR_SIZE;
365                 ptr = buf;
366 readhdr:
367                 rc = read(fdin, ptr, count);
368                 if (rc <= 0)
369                         goto print;
370
371                 ptr += rc;
372                 count -= rc;
373                 if (count > 0)
374                         goto readhdr;
375
376                 if (hdr->ph_len > 4094 ||       /* is this header bogus? */
377                     hdr->ph_stack > 65536 ||
378                     hdr->ph_sec < (1 << 30) ||
379                     hdr->ph_usec > 1000000000 ||
380                     hdr->ph_line_num > 65536) {
381                         if (first_bad)
382                                 dump_hdr(lseek(fdin, 0, SEEK_CUR), hdr);
383                         bad += first_bad;
384                         first_bad = 0;
385
386                         /* try to restart on next line */
387                         while (count < HDR_SIZE && buf[count] != '\n')
388                                 count++;
389                         if (buf[count] == '\n')
390                                 count++; /* move past '\n' */
391                         if (HDR_SIZE - count > 0) {
392                                 int left = HDR_SIZE - count;
393
394                                 memmove(buf, buf + count, left);
395                                 ptr = buf + left;
396
397                                 goto readhdr;
398                         }
399
400                         continue;
401                 }
402
403                 if (hdr->ph_len == 0)
404                         continue;
405
406                 count = hdr->ph_len - HDR_SIZE;
407 readmore:
408                 rc = read(fdin, ptr, count);
409                 if (rc <= 0)
410                         break;
411
412                 ptr += rc;
413                 count -= rc;
414                 if (count > 0)
415                         goto readmore;
416
417                 first_bad = 1;
418
419                 if ((hdr->ph_subsys && !(subsystem_mask & hdr->ph_subsys)) ||
420                     (hdr->ph_mask && !(debug_mask & hdr->ph_mask))) {
421                         dropped++;
422                         continue;
423                 }
424
425 retry_alloc:
426                 line = malloc(sizeof(*line));
427                 if (line == NULL) {
428                         if (linev) {
429                                 fprintf(stderr, "error: line malloc(%u): "
430                                         "printing accumulated records\n",
431                                         (unsigned int)sizeof(*line));
432                                 print_rec(&linev, kept, fdout);
433
434                                 goto retry_alloc;
435                         }
436                         fprintf(stderr, "error: line malloc(%u): exiting\n",
437                                 (unsigned int)sizeof(*line));
438                         break;
439                 }
440
441                 line->hdr = malloc(hdr->ph_len + 1);
442                 if (line->hdr == NULL) {
443                         free(line);
444                         if (linev) {
445                                 fprintf(stderr, "error: hdr malloc(%u): "
446                                         "printing accumulated records\n",
447                                         hdr->ph_len + 1);
448                                 print_rec(&linev, kept, fdout);
449
450                                 goto retry_alloc;
451                         }
452                         fprintf(stderr, "error: hdr malloc(%u): exiting\n",
453                                         hdr->ph_len + 1);
454                         break;
455                 }
456
457                 ptr = (void *)line->hdr;
458                 memcpy(line->hdr, buf, hdr->ph_len);
459                 ptr[hdr->ph_len] = '\0';
460
461                 ptr += sizeof(*hdr);
462                 line->file = ptr;
463                 ptr += strlen(line->file) + 1;
464                 line->fn = ptr;
465                 ptr += strlen(line->fn) + 1;
466                 line->text = ptr;
467
468 retry_add:
469                 if (add_rec(line, &linev, &linev_len, kept) < 0) {
470                         if (linev) {
471                                 fprintf(stderr, "error: add_rec[%u] failed; "
472                                         "print accumulated records\n",
473                                         linev_len);
474                                 print_rec(&linev, kept, fdout);
475
476                                 goto retry_add;
477                         }
478                         fprintf(stderr, "error: add_rec[0] failed; exiting\n");
479                         break;
480                 }
481                 kept++;
482         }
483
484 print:
485         if (linev)
486                 print_rec(&linev, kept, fdout);
487
488         printf("Debug log: %lu lines, %lu kept, %lu dropped, %lu bad.\n",
489                 dropped + kept + bad, kept, dropped, bad);
490
491         return 0;
492 }
493
494 int jt_dbg_debug_kernel(int argc, char **argv)
495 {
496         struct stat     st;
497         char            filename[PATH_MAX];
498         int             raw = 0;
499         int             save_errno;
500         int             fdin;
501         int             fdout;
502         int             rc;
503
504         if (argc > 3) {
505                 fprintf(stderr, "usage: %s [file] [raw]\n", argv[0]);
506                 return 0;
507         }
508
509         if (argc > 2) {
510                 raw = atoi(argv[2]);
511         } else if (argc > 1 && (argv[1][0] == '0' || argv[1][0] == '1')) {
512                 raw = atoi(argv[1]);
513                 argc--;
514         }
515
516         /* If we are dumping raw (which means no conversion step to ASCII)
517          * then dump directly to any supplied filename, otherwise this is
518          * just a temp file and we dump to the real file at convert time. */
519         if (argc > 1 && raw) {
520                 if (strlen(argv[1]) >= sizeof(filename)) {
521                         fprintf(stderr, "File name too long: %s\n", argv[1]);
522                         return 1;
523                 }
524                 strncpy(filename, argv[1], sizeof(filename));
525         } else {
526                 if (snprintf(filename, sizeof(filename), "%s"CFS_TIME_T".%u",
527                              LIBCFS_DEBUG_FILE_PATH_DEFAULT, time(NULL),
528                              getpid())
529                     >= sizeof(filename)) {
530                         fprintf(stderr, "File name too long\n");
531                         return 1;
532                 }
533         }
534
535         if (stat(filename, &st) == 0 && S_ISREG(st.st_mode))
536                 unlink(filename);
537
538         fdin = dbg_open_ctlhandle(DUMP_KERNEL_CTL_NAME);
539         if (fdin < 0) {
540                 fprintf(stderr, "open(dump_kernel) failed: %s\n",
541                         strerror(errno));
542                 return 1;
543         }
544
545         rc = dbg_write_cmd(fdin, filename, strlen(filename));
546         save_errno = errno;
547         dbg_close_ctlhandle(fdin);
548         if (rc != 0) {
549                 fprintf(stderr, "write(%s) failed: %s\n", filename,
550                         strerror(save_errno));
551                 return 1;
552         }
553
554         if (raw)
555                 return 0;
556
557         fdin = open(filename, O_RDONLY);
558         if (fdin < 0) {
559                 if (errno == ENOENT) /* no dump file created */
560                         return 0;
561                 fprintf(stderr, "fopen(%s) failed: %s\n", filename,
562                         strerror(errno));
563                 return 1;
564         }
565         if (argc > 1) {
566                 fdout = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC,
567                              S_IRUSR | S_IWUSR);
568                 if (fdout < 0) {
569                         fprintf(stderr, "fopen(%s) failed: %s\n", argv[1],
570                                 strerror(errno));
571                         close(fdin);
572                         return 1;
573                 }
574         } else {
575                 fdout = fileno(stdout);
576         }
577
578         rc = parse_buffer(fdin, fdout);
579         close(fdin);
580         if (argc > 1)
581                 close(fdout);
582         if (rc) {
583                 fprintf(stderr, "parse_buffer failed; leaving tmp file %s "
584                         "behind.\n", filename);
585         } else {
586                 rc = unlink(filename);
587                 if (rc)
588                         fprintf(stderr, "dumped successfully, but couldn't "
589                                 "unlink tmp file %s: %s\n", filename,
590                                 strerror(errno));
591         }
592
593         return rc;
594 }
595
596 int jt_dbg_debug_file(int argc, char **argv)
597 {
598         int fdin;
599         int fdout;
600         int rc;
601
602         if (argc > 3 || argc < 2) {
603                 fprintf(stderr, "usage: %s <input> [output]\n", argv[0]);
604                 return 0;
605         }
606
607         fdin = open(argv[1], O_RDONLY | O_LARGEFILE);
608         if (fdin < 0) {
609                 fprintf(stderr, "open(%s) failed: %s\n", argv[1],
610                         strerror(errno));
611                 return 1;
612         }
613         if (argc > 2) {
614                 fdout = open(argv[2],
615                              O_CREAT | O_TRUNC | O_WRONLY | O_LARGEFILE,
616                              0600);
617                 if (fdout < 0) {
618                         fprintf(stderr, "open(%s) failed: %s\n", argv[2],
619                                 strerror(errno));
620                         close(fdin);
621                         return 1;
622                 }
623         } else {
624                 fdout = fileno(stdout);
625         }
626
627         rc = parse_buffer(fdin, fdout);
628
629         close(fdin);
630         if (fdout != fileno(stdout))
631                 close(fdout);
632
633         return rc;
634 }
635
636 const char debug_daemon_usage[] = "usage: %s {start file [MB]|stop}\n";
637
638 int jt_dbg_debug_daemon(int argc, char **argv)
639 {
640         int rc;
641         int fd;
642
643         if (argc <= 1) {
644                 fprintf(stderr, debug_daemon_usage, argv[0]);
645                 return 1;
646         }
647
648         fd = dbg_open_ctlhandle(DAEMON_CTL_NAME);
649         if (fd < 0)
650                 return -1;
651
652         rc = -1;
653         if (strcasecmp(argv[1], "start") == 0) {
654                 if (argc < 3 || argc > 4 ||
655                     (argc == 4 && strlen(argv[3]) > 5)) {
656                         fprintf(stderr, debug_daemon_usage, argv[0]);
657                         goto out;
658                 }
659                 if (argc == 4) {
660                         char             buf[12];
661                         const long       min_size = 10;
662                         const long       max_size = 20480;
663                         long             size;
664                         char            *end;
665
666                         size = strtoul(argv[3], &end, 0);
667                         if (size < min_size ||
668                             size > max_size ||
669                             *end != 0) {
670                                 fprintf(stderr, "size %s invalid, must be in "
671                                         "the range %ld-%ld MB\n", argv[3],
672                                         min_size, max_size);
673                                 goto out;
674                         }
675                         snprintf(buf, sizeof(buf), "size=%ld", size);
676                         rc = dbg_write_cmd(fd, buf, strlen(buf));
677
678                         if (rc != 0) {
679                                 fprintf(stderr, "set %s failed: %s\n",
680                                         buf, strerror(errno));
681                                 goto out;
682                         }
683                 }
684
685                 rc = dbg_write_cmd(fd, argv[2], strlen(argv[2]));
686                 if (rc != 0) {
687                         fprintf(stderr, "start debug_daemon on %s failed: %s\n",
688                                 argv[2], strerror(errno));
689                         goto out;
690                 }
691                 rc = 0;
692                 goto out;
693         }
694         if (strcasecmp(argv[1], "stop") == 0) {
695                 rc = dbg_write_cmd(fd, "stop", 4);
696                 if (rc != 0) {
697                         fprintf(stderr, "stopping debug_daemon failed: %s\n",
698                                 strerror(errno));
699                         goto out;
700                 }
701
702                 rc = 0;
703                 goto out;
704         }
705
706         fprintf(stderr, debug_daemon_usage, argv[0]);
707         rc = -1;
708 out:
709         dbg_close_ctlhandle(fd);
710         return rc;
711 }
712
713 int jt_dbg_clear_debug_buf(int argc, char **argv)
714 {
715         int                      rc;
716         struct libcfs_ioctl_data data;
717
718         if (argc != 1) {
719                 fprintf(stderr, "usage: %s\n", argv[0]);
720                 return 0;
721         }
722
723         memset(&data, 0, sizeof(data));
724         if (libcfs_ioctl_pack(&data, &buf, max) != 0) {
725                 fprintf(stderr, "libcfs_ioctl_pack failed.\n");
726                 return -1;
727         }
728
729         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CLEAR_DEBUG, buf);
730         if (rc) {
731                 fprintf(stderr, "IOC_LIBCFS_CLEAR_DEBUG failed: %s\n",
732                         strerror(errno));
733                 return -1;
734         }
735         return 0;
736 }
737
738 int jt_dbg_mark_debug_buf(int argc, char **argv)
739 {
740         static char              scratch[MAX_MARK_SIZE] = "";
741         struct libcfs_ioctl_data data;
742         char                    *text;
743         int                      rc;
744
745         memset(&data, 0, sizeof(data));
746
747         if (argc > 1) {
748                 int count, max_size = sizeof(scratch) - 1;
749
750                 strncpy(scratch, argv[1], max_size);
751                 max_size -= strlen(argv[1]);
752                 for (count = 2; (count < argc) && (max_size > 1); count++) {
753                         strncat(scratch, " ", max_size);
754                         max_size -= 1;
755                         strncat(scratch, argv[count], max_size);
756                         max_size -= strlen(argv[count]);
757                 }
758                 scratch[sizeof(scratch) - 1] = '\0';
759                 text = scratch;
760         } else {
761                 time_t now = time(NULL);
762                 text = ctime(&now);
763         }
764
765         data.ioc_inllen1 = strlen(text) + 1;
766         data.ioc_inlbuf1 = text;
767
768         if (libcfs_ioctl_pack(&data, &buf, max) != 0) {
769                 fprintf(stderr, "libcfs_ioctl_pack failed.\n");
770                 return -1;
771         }
772
773         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_MARK_DEBUG, buf);
774         if (rc) {
775                 fprintf(stderr, "IOC_LIBCFS_MARK_DEBUG failed: %s\n",
776                         strerror(errno));
777                 return -1;
778         }
779         return 0;
780 }
781
782 static struct mod_paths {
783         char *name, *path;
784 } mod_paths[] = {
785         { "libcfs", "libcfs/libcfs" },
786         { "lnet", "lnet/lnet" },
787         { "ko2iblnd", "lnet/klnds/o2iblnd" },
788         { "kgnilnd", "lnet/klnds/gnilnd"},
789         { "ksocklnd", "lnet/klnds/socklnd" },
790         { "obdclass", "lustre/obdclass" },
791         { "llog_test", "lustre/obdclass" },
792         { "ptlrpc_gss", "lustre/ptlrpc/gss" },
793         { "ptlrpc", "lustre/ptlrpc" },
794         { "gks", "lustre/sec/gks" },
795         { "gkc", "lustre/sec/gks" },
796         { "ost", "lustre/ost" },
797         { "osc", "lustre/osc" },
798         { "mds", "lustre/mds" },
799         { "mdc", "lustre/mdc" },
800         { "lustre", "lustre/llite" },
801         { "llite_lloop", "lustre/llite" },
802         { "ldiskfs", "ldiskfs" },
803         { "obdecho", "lustre/obdecho" },
804         { "ldlm", "lustre/ldlm" },
805         { "obdfilter", "lustre/obdfilter" },
806         { "lov", "lustre/lov" },
807         { "lmv", "lustre/lmv" },
808         { "lquota", "lustre/quota" },
809         { "mgs", "lustre/mgs" },
810         { "mgc", "lustre/mgc" },
811         { "mdt", "lustre/mdt" },
812         { "mdd", "lustre/mdd" },
813         { "osd", "lustre/osd" },
814         { "cmm", "lustre/cmm" },
815         {"fid", "lustre/fid"},
816         {"fld", "lustre/fld"},
817         {"lod", "lustre/lod"},
818         {"osp", "lustre/osp"},
819         { "lfsck", "lustre/lfsck" },
820         {NULL, NULL}
821 };
822
823 int jt_dbg_modules(int argc, char **argv)
824 {
825         struct mod_paths *mp;
826         char             *path = "";
827         const char       *proc = "/proc/modules";
828         char              modname[128];
829         char              buf[4096];
830         unsigned long     modaddr;
831         FILE             *file;
832
833         if (argc >= 2)
834                 path = argv[1];
835         if (argc > 3) {
836                 printf("%s [path] [kernel]\n", argv[0]);
837                 return 0;
838         }
839
840         file = fopen(proc, "r");
841         if (!file) {
842                 printf("failed open %s: %s\n", proc, strerror(errno));
843                 return 0;
844         }
845
846         while (fgets(buf, sizeof(buf), file) != NULL) {
847                 if (sscanf(buf, "%s %*s %*s %*s %*s %lx",
848                            modname, &modaddr) == 2) {
849                         for (mp = mod_paths; mp->name != NULL; mp++) {
850                                 if (!strcmp(mp->name, modname))
851                                         break;
852                         }
853                         if (mp->name) {
854                                 printf("add-symbol-file %s%s%s/%s.o 0x%0lx\n",
855                                         path, path[0] ? "/" : "",
856                                         mp->path, mp->name, modaddr);
857                         }
858                 }
859         }
860
861         fclose(file);
862         return 0;
863 }