DF-5171 / vcd_flush_poc.c
/* * DF-5171 PoC (B) - vcdstrategy() panics on BUF_CMD_FLUSH (HAMMER path). * * Runs as PID1 inside: vkernel64 -m 256M -r root.img -c hammer.img \ * -e init_path=/poc * * Chain: mount -o rw hammer /dev/vcd0 /mnt * -> mount-time recovery and/or the first flusher cycle call * hammer_io_wait_all(..., 1) -> hammer_io_flush_sync() * -> BUF_CMD_FLUSH bio (b_bcount=0, bio_offset=0) via * vn_strategy(volume->devvp) (hammer_io.c:1989-2007) * -> diskstrategy -> dscheck (passes) -> vcdstrategy() * -> default: panic("vcd: bad b_cmd 5") * * Expected: "MOUNTING hammer..." then vkernel panic * "panic: vcd: bad b_cmd 5"; mount(2) never returns. */ #include <errno.h> #include <fcntl.h> #include <stdint.h> #include <stdarg.h> #include <stdio.h> #include <unistd.h> #include <sys/mount.h> int mount(const char *, const char *, int, void *); /* verbatim from sys/vfs/hammer/hammer_mount.h (same order = same layout) */ struct hammer_mount_info { char **volumes; /* array of pointers to device names */ int nvolumes; /* number of devices */ int hflags; /* extended hammer mount flags */ int master_id; /* -1=no-mirror mode, or 0-15 */ uint64_t asof; /* asof - HAMMER_MAX_TID is current */ char reserved1[136]; /* was struct export_args */ uint64_t reserved2[15]; }; static int consfd = -1; static void logmark(const char *fmt, ...) { va_list ap; char buf[512]; int n; va_start(ap, fmt); n = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (n > 0) { int fd = open("/marker", O_WRONLY | O_CREAT | O_APPEND, 0644); if (fd >= 0) { write(fd, buf, n); close(fd); } if (consfd < 0) consfd = open("/dev/console", O_WRONLY); if (consfd >= 0) write(consfd, buf, n); } } int main(void) { static struct hammer_mount_info info; static char *vols[2]; logmark("DF-5171(B) vcd FLUSH panic PoC (hammer) start\n"); mkdir("/mnt", 0777); vols[0] = "/dev/vcd0"; info.volumes = vols; info.nvolumes = 1; info.master_id = -1; logmark("MOUNTING hammer on /dev/vcd0 (rw)...\n"); if (mount("hammer", "/mnt", 0 /* rw */, &info) < 0) { logmark("mount(hammer) FAILED errno=%d\n", errno); logmark("RESULT: mount-failed\n"); return (1); } logmark("mount(hammer) returned OK\n"); sleep(15); logmark("RESULT: no-panic (STILL ALIVE after 15s)\n"); return (0); } |