diff options
author | behlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c> | 2008-04-18 23:39:58 +0000 |
---|---|---|
committer | behlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c> | 2008-04-18 23:39:58 +0000 |
commit | 57d1b1885897c9b079a6355a6d54d684ad003d46 (patch) | |
tree | 941352e2acfedadd3b97f0af780a2a7a2e910540 /cmd | |
parent | 55152ebbb46fb8e382ed18e58cc570c61e224c21 (diff) |
First commit of lustre style internal debug support. These
changes bring over everything lustre had for debugging with
two exceptions. I dropped by the debug daemon and upcalls
just because it made things a little easier. They can be
readded easily enough if we feel they are needed.
Everything compiles and seems to work on first inspection
but I suspect there are a handful of issues still lingering
which I'll be sorting out right away. I just wanted to get
all these changes commited and safe. I'm getting a little
paranoid about losing them.
git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@75 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/Makefile.am | 7 | ||||
-rw-r--r-- | cmd/spl.c | 217 |
2 files changed, 222 insertions, 2 deletions
diff --git a/cmd/Makefile.am b/cmd/Makefile.am index d3d747797..3d1a39297 100644 --- a/cmd/Makefile.am +++ b/cmd/Makefile.am @@ -1,7 +1,10 @@ DEFAULT_INCLUDES = -I. -I.. -I../lib -AM_CFLAGS = -g -O2 -W -Wall -Wstrict-prototypes -Wshadow +AM_CFLAGS = -g -O2 -W -Wall -Wstrict-prototypes -Wshadow -D__USE_LARGEFILE64 + +sbin_PROGRAMS = spl splat + +spl_SOURCES = spl.c -sbin_PROGRAMS = splat splat_SOURCES = splat.c splat_LDFLAGS = $(top_builddir)/lib/libcommon.la diff --git a/cmd/spl.c b/cmd/spl.c new file mode 100644 index 000000000..866bc8905 --- /dev/null +++ b/cmd/spl.c @@ -0,0 +1,217 @@ +#include <stdlib.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include "../include/spl-ctl.h" + +static int spl_debug_mask = ~0; +static int spl_debug_subsystem = ~0; + +/* all strings nul-terminated; only the struct and hdr need to be freed */ +struct dbg_line { + struct spl_debug_header *hdr; + char *file; + char *fn; + char *text; +}; + +static int +cmp_rec(const void *p1, const void *p2) +{ + struct dbg_line *d1 = *(struct dbg_line **)p1; + struct dbg_line *d2 = *(struct dbg_line **)p2; + + if (d1->hdr->ph_sec < d2->hdr->ph_sec) + return -1; + + if (d1->hdr->ph_sec == d2->hdr->ph_sec && + d1->hdr->ph_usec < d2->hdr->ph_usec) + return -1; + + if (d1->hdr->ph_sec == d2->hdr->ph_sec && + d1->hdr->ph_usec == d2->hdr->ph_usec) + return 0; + + return 1; +} + +static void +print_rec(struct dbg_line **linev, int used, FILE *out) +{ + int i; + + for (i = 0; i < used; i++) { + struct dbg_line *line = linev[i]; + struct spl_debug_header *hdr = line->hdr; + + fprintf(out, "%08x:%08x:%u:%u.%06llu:%u:%u:(%s:%u:%s()) %s", + hdr->ph_subsys, hdr->ph_mask, hdr->ph_cpu_id, + hdr->ph_sec, (unsigned long long)hdr->ph_usec, + hdr->ph_stack, hdr->ph_pid, line->file, + hdr->ph_line_num, line->fn, line->text); + free(line->hdr); + free(line); + } + + free(linev); +} + +static int +add_rec(struct dbg_line *line, struct dbg_line ***linevp, int *lenp, int used) +{ + struct dbg_line **linev = *linevp; + + if (used == *lenp) { + int nlen = *lenp + 512; + int nsize = nlen * sizeof(struct dbg_line *); + + linev = *linevp ? realloc(*linevp, nsize) : malloc(nsize); + if (!linev) + return 0; + *linevp = linev; + *lenp = nlen; + } + linev[used] = line; + return 1; +} + +static int +parse_buffer(FILE *in, FILE *out) +{ + struct dbg_line *line; + struct spl_debug_header *hdr; + char buf[4097], *p; + unsigned long dropped = 0, kept = 0; + struct dbg_line **linev = NULL; + const int phl = sizeof(hdr->ph_len); + const int phf = sizeof(hdr->ph_flags); + int rc, linev_len = 0; + + while (1) { + rc = fread(buf, phl + phf, 1, in); + if (rc <= 0) + break; + + hdr = (void *)buf; + if (hdr->ph_len == 0) + break; + if (hdr->ph_len > 4094) { + fprintf(stderr, "unexpected large record: %d bytes. " + "aborting.\n", hdr->ph_len); + break; + } + + rc = fread(buf + phl + phf, 1, hdr->ph_len - phl - phf, in); + if (rc <= 0) + break; + + if (hdr->ph_mask && + (!(spl_debug_subsystem & hdr->ph_subsys) || + (!(spl_debug_mask & hdr->ph_mask)))) { + dropped++; + continue; + } + + line = malloc(sizeof(*line)); + if (line == NULL) { + fprintf(stderr, "malloc failed; printing accumulated " + "records and exiting.\n"); + break; + } + + line->hdr = malloc(hdr->ph_len + 1); + if (line->hdr == NULL) { + free(line); + fprintf(stderr, "malloc failed; printing accumulated " + "records and exiting.\n"); + break; + } + + p = (void *)line->hdr; + memcpy(line->hdr, buf, hdr->ph_len); + p[hdr->ph_len] = '\0'; + + p += sizeof(*hdr); + line->file = p; + p += strlen(line->file) + 1; + line->fn = p; + p += strlen(line->fn) + 1; + line->text = p; + + if (!add_rec(line, &linev, &linev_len, kept)) { + fprintf(stderr, "malloc failed; printing accumulated " + "records and exiting.\n"); + break; + } + kept++; + } + + if (linev) { + qsort(linev, kept, sizeof(struct dbg_line *), cmp_rec); + print_rec(linev, kept, out); + } + + printf("Debug log: %lu lines, %lu kept, %lu dropped.\n", + dropped + kept, kept, dropped); + return 0; +} + +int +main(int argc, char *argv[]) +{ + int fdin, fdout; + FILE *in, *out = stdout; + int rc, o_lf = 0; + + if (argc > 3 || argc < 2) { + fprintf(stderr, "usage: %s <input> [output]\n", argv[0]); + return 0; + } + +#ifdef __USE_LARGEFILE64 + o_lf = O_LARGEFILE; +#endif + + fdin = open(argv[1], O_RDONLY | o_lf); + if (fdin == -1) { + fprintf(stderr, "open(%s) failed: %s\n", argv[1], + strerror(errno)); + return 1; + } + in = fdopen(fdin, "r"); + if (in == NULL) { + fprintf(stderr, "fopen(%s) failed: %s\n", argv[1], + strerror(errno)); + close(fdin); + return 1; + } + if (argc > 2) { + fdout = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | o_lf, 0600); + if (fdout == -1) { + fprintf(stderr, "open(%s) failed: %s\n", argv[2], + strerror(errno)); + fclose(in); + return 1; + } + out = fdopen(fdout, "w"); + if (out == NULL) { + fprintf(stderr, "fopen(%s) failed: %s\n", argv[2], + strerror(errno)); + fclose(in); + close(fdout); + return 1; + } + } + + rc = parse_buffer(in, out); + + fclose(in); + if (out != stdout) + fclose(out); + + return rc; +} |