DF-2832 / churn_open.c
/* * DF-2832 open/unlink churner (unprivileged). * * Every open(O_CREAT|O_WRONLY) goes through ncp_writechk() -> * VFS_MODIFYING() -> hammer2_vfs_modifying() -> * hammer2_pfs_memory_wait() -> trigger_syncer()/trigger_syncer_start() * (sys/kern/vfs_sync.c) which load mp->mnt_syncer_ctx lock-free. * * With vfs.hammer2.limit_dirty_chains lowered, the churner spends nearly * all its time stalled inside hammer2_pfs_memory_wait -- i.e. inside or * adjacent to the trigger_syncer*() window -- while holding NO vnode * locks and (mid-open) NO fd on the mount, so dounmount()'s process-kill * scan (process_uses_mount, vfs_syscalls.c) does not match it. * * usage: churn_open <dir> <secs> */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <time.h> int main(int argc, char **argv) { char path[512]; char buf[65536]; time_t deadline; unsigned long n = 0; if (argc < 3) { fprintf(stderr, "usage: %s <dir> <secs>\n", argv[0]); return (2); } deadline = time(NULL) + atoi(argv[2]); memset(buf, 'X', sizeof(buf)); while (time(NULL) < deadline) { snprintf(path, sizeof(path), "%s/c.%d.%d", argv[1], (int)getpid(), (int)(n & 7)); int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd >= 0) { write(fd, buf, sizeof(buf)); /* dirty a chain */ close(fd); unlink(path); n++; } else { usleep(10000); /* mount between mounts */ } } fprintf(stderr, "churn_open: %lu cycles\n", n); return (0); } |