DF-4760 / hold_daemon.c
/* * DF-4760 — holder for /dev/vinum/controld (the vinum daemon device). * * free_vinum() (sys/dev/raid/vinum/vinum.c:215-219) contains: * * while ((vinum_conf.flags & (VF_STOPPING | VF_DAEMONOPEN)) * == (VF_STOPPING | VF_DAEMONOPEN)) { * queue_daemon_request(daemonrq_return, di); // kmalloc every pass * tsleep(&vinumclose, 0, "vstop", 1); // 1 tick * } * * Opening /dev/vinum/controld (root-only, 0600) sets VF_DAEMONOPEN but * does NOT start the kernel vinum_daemon thread; and even if that thread * is running, its very first daemonrq_return makes it drain the queue and * EXIT (vinumdaemon.c:150-162) — so after at most one consumed request, * nothing ever drains the queue again. Every subsequent loop iteration * (100/s) kmalloc()s a struct daemonq that is never freed, and the loop * only ends when this holder closes the device. * * While this process holds the fd, `kldunload vinum` therefore: * 1. hangs forever in the free_vinum() loop (tsleep channel "vstop"), and * 2. leaks kernel memory at ~100 * sizeof(struct daemonq) bytes/second. * * Build: cc -O -o hold_daemon hold_daemon.c * Run: ./hold_daemon <seconds-to-hold> */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main(int argc, char **argv) { int hold = (argc > 1) ? atoi(argv[1]) : 30; int fd = open("/dev/vinum/controld", O_RDWR); if (fd < 0) { perror("open /dev/vinum/controld"); return 1; } printf("[holder] opened /dev/vinum/controld fd=%d (VF_DAEMONOPEN set); " "holding for %ds\n", fd, hold); fflush(stdout); sleep(hold); printf("[holder] closing now - free_vinum loop should exit\n"); fflush(stdout); close(fd); sleep(1); printf("[holder] done\n"); fflush(stdout); return 0; } |