diff options
author | Etienne Dechamps <[email protected]> | 2012-10-04 16:09:12 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2012-10-04 13:19:09 -0700 |
commit | 9d81146b015e8f4f611357c4cef17fbfb2f4bd54 (patch) | |
tree | be885190d6faf4c916b91e6474551dca508f5af3 /cmd/ztest | |
parent | 22257dc0d5582035347320130e9ee03b33dffb6f (diff) |
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 <[email protected]>
Diffstat (limited to 'cmd/ztest')
-rw-r--r-- | cmd/ztest/ztest.c | 59 |
1 files changed, 28 insertions, 31 deletions
diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 9da15a185..973e7b2f6 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -121,8 +121,8 @@ #include <sys/fs/zfs.h> #include <libnvpair.h> -#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; |