mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
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
This commit is contained in:
+5
-2
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user