From: Etienne Dechamps Date: Thu, 4 Oct 2012 14:09:12 +0000 (+0200) Subject: Use dynamic file descriptor numbers in ztest. X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=commitdiff_plain;h=9d81146b015e8f4f611357c4cef17fbfb2f4bd54;p=zfs.git Use dynamic file descriptor numbers in ztest. Currently, ztest expects to get 3 and 4 as the file descriptors for data and random files, respectively. This is quite fragile and breaks easily if ztest is run with these file descriptors already opened (e.g. in a complex shell script). This patch fixes the issue by removing the assumptions on the file descriptor numbers that open() returns. For the random file (/dev/urandom), the new code doesn't rely on a shared file descriptor; instead, it reopens the file in the child. For the data file, the new code writes the file descriptor number into a "ZTEST_FD_DATA" environment variable so that it can be recovered after the execv() call. Signed-off-by: Brian Behlendorf --- diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 9da15a1..973e7b2 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -121,8 +121,8 @@ #include #include -#define ZTEST_FD_DATA 3 -#define ZTEST_FD_RAND 4 +static int ztest_fd_data = -1; +static int ztest_fd_rand = -1; typedef struct ztest_shared_hdr { uint64_t zh_hdr_size; @@ -783,10 +783,12 @@ ztest_random(uint64_t range) { uint64_t r; + ASSERT3S(ztest_fd_rand, >=, 0); + if (range == 0) return (0); - if (read(ZTEST_FD_RAND, &r, sizeof (r)) != sizeof (r)) + if (read(ztest_fd_rand, &r, sizeof (r)) != sizeof (r)) fatal(1, "short read from /dev/urandom"); return (r % range); @@ -5815,26 +5817,13 @@ ztest_init(ztest_shared_t *zs) } static void -setup_fds(void) +setup_data_fd(void) { - int fd; - char *tmp = tempnam(NULL, NULL); - fd = open(tmp, O_RDWR | O_CREAT, 0700); - ASSERT3S(fd, >=, 0); - if (fd != ZTEST_FD_DATA) { - VERIFY3S(dup2(fd, ZTEST_FD_DATA), ==, ZTEST_FD_DATA); - close(fd); - } + ztest_fd_data = open(tmp, O_RDWR | O_CREAT, 0700); + ASSERT3S(ztest_fd_data, >=, 0); (void) unlink(tmp); free(tmp); - - fd = open("/dev/urandom", O_RDONLY); - ASSERT3S(fd, >=, 0); - if (fd != ZTEST_FD_RAND) { - VERIFY3S(dup2(fd, ZTEST_FD_RAND), ==, ZTEST_FD_RAND); - close(fd); - } } static int @@ -5858,10 +5847,10 @@ setup_hdr(void) ztest_shared_hdr_t *hdr; hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), - PROT_READ | PROT_WRITE, MAP_SHARED, ZTEST_FD_DATA, 0); + PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); ASSERT(hdr != MAP_FAILED); - VERIFY3U(0, ==, ftruncate(ZTEST_FD_DATA, sizeof (ztest_shared_hdr_t))); + VERIFY3U(0, ==, ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t))); hdr->zh_hdr_size = sizeof (ztest_shared_hdr_t); hdr->zh_opts_size = sizeof (ztest_shared_opts_t); @@ -5872,7 +5861,7 @@ setup_hdr(void) hdr->zh_ds_count = ztest_opts.zo_datasets; size = shared_data_size(hdr); - VERIFY3U(0, ==, ftruncate(ZTEST_FD_DATA, size)); + VERIFY3U(0, ==, ftruncate(ztest_fd_data, size)); (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); } @@ -5885,14 +5874,14 @@ setup_data(void) uint8_t *buf; hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), - PROT_READ, MAP_SHARED, ZTEST_FD_DATA, 0); + PROT_READ, MAP_SHARED, ztest_fd_data, 0); ASSERT(hdr != MAP_FAILED); size = shared_data_size(hdr); (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); hdr = ztest_shared_hdr = (void *)mmap(0, P2ROUNDUP(size, getpagesize()), - PROT_READ | PROT_WRITE, MAP_SHARED, ZTEST_FD_DATA, 0); + PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); ASSERT(hdr != MAP_FAILED); buf = (uint8_t *)hdr; @@ -5925,9 +5914,15 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp) if (pid == 0) { /* child */ char *emptyargv[2] = { cmd, NULL }; + char fd_data_str[12]; struct rlimit rl = { 1024, 1024 }; (void) setrlimit(RLIMIT_NOFILE, &rl); + + (void) close(ztest_fd_rand); + VERIFY(11 >= snprintf(fd_data_str, 12, "%d", ztest_fd_data)); + VERIFY(0 == setenv("ZTEST_FD_DATA", fd_data_str, 1)); + (void) enable_extended_FILE_stdio(-1, -1); if (libpath != NULL) VERIFY(0 == setenv("LD_LIBRARY_PATH", libpath, 1)); @@ -6005,22 +6000,24 @@ main(int argc, char **argv) char cmd[MAXNAMELEN]; boolean_t hasalt; int f; - boolean_t ischild = (0 == lseek(ZTEST_FD_DATA, 0, SEEK_CUR)); - - ASSERT(ischild || errno == EBADF || errno == ESPIPE); + char *fd_data_str = getenv("ZTEST_FD_DATA"); (void) setvbuf(stdout, NULL, _IOLBF, 0); - if (!ischild) { + ztest_fd_rand = open("/dev/urandom", O_RDONLY); + ASSERT3S(ztest_fd_rand, >=, 0); + + if (!fd_data_str) { dprintf_setup(&argc, argv); process_options(argc, argv); - setup_fds(); + setup_data_fd(); setup_hdr(); setup_data(); bcopy(&ztest_opts, ztest_shared_opts, sizeof (*ztest_shared_opts)); } else { + ztest_fd_data = atoi(fd_data_str); setup_data(); bcopy(ztest_shared_opts, &ztest_opts, sizeof (ztest_opts)); } @@ -6029,12 +6026,12 @@ main(int argc, char **argv) /* Override location of zpool.cache */ (void) asprintf((char **)&spa_config_path, "%s/zpool.cache", ztest_opts.zo_dir); - + ztest_ds = umem_alloc(ztest_opts.zo_datasets * sizeof (ztest_ds_t), UMEM_NOFAIL); zs = ztest_shared; - if (ischild) { + if (fd_data_str) { metaslab_gang_bang = ztest_opts.zo_metaslab_gang_bang; metaslab_df_alloc_threshold = zs->zs_metaslab_df_alloc_threshold;