aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>2008-04-18 23:39:58 +0000
committerbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>2008-04-18 23:39:58 +0000
commit57d1b1885897c9b079a6355a6d54d684ad003d46 (patch)
tree941352e2acfedadd3b97f0af780a2a7a2e910540 /cmd
parent55152ebbb46fb8e382ed18e58cc570c61e224c21 (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.am7
-rw-r--r--cmd/spl.c217
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;
+}