mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-27 18:34:22 +03:00
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 <behlendorf1@llnl.gov>
This commit is contained in:
parent
22257dc0d5
commit
9d81146b01
@ -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));
|
||||
}
|
||||
@ -6034,7 +6031,7 @@ main(int argc, char **argv)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user