Skip to content

Commit 741652b

Browse files
committed
3258 ztest's use of file descriptors is unstable
Reviewed by: Christopher Siden <chris.siden@delphix.com> Reviewed by: Matt Ahrens <matthew.ahrens@delphix.com> Approved by: Garrett D'Amore <garrett@damore.org>
1 parent 989f280 commit 741652b

File tree

1 file changed

+55
-33
lines changed

1 file changed

+55
-33
lines changed

usr/src/cmd/ztest/ztest.c

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@
119119
#include <sys/fs/zfs.h>
120120
#include <libnvpair.h>
121121

122-
#define ZTEST_FD_DATA 3
123-
#define ZTEST_FD_RAND 4
122+
static int ztest_fd_data = -1;
123+
static int ztest_fd_rand = -1;
124124

125125
typedef struct ztest_shared_hdr {
126126
uint64_t zh_hdr_size;
@@ -708,14 +708,17 @@ process_options(int argc, char **argv)
708708
UINT64_MAX >> 2);
709709

710710
if (strlen(altdir) > 0) {
711-
char cmd[MAXNAMELEN];
712-
char realaltdir[MAXNAMELEN];
711+
char *cmd;
712+
char *realaltdir;
713713
char *bin;
714714
char *ztest;
715715
char *isa;
716716
int isalen;
717717

718-
(void) realpath(getexecname(), cmd);
718+
cmd = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
719+
realaltdir = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
720+
721+
VERIFY(NULL != realpath(getexecname(), cmd));
719722
if (0 != access(altdir, F_OK)) {
720723
ztest_dump_core = B_FALSE;
721724
fatal(B_TRUE, "invalid alternate ztest path: %s",
@@ -746,6 +749,9 @@ process_options(int argc, char **argv)
746749
fatal(B_TRUE, "invalid alternate lib directory %s",
747750
zo->zo_alt_libpath);
748751
}
752+
753+
umem_free(cmd, MAXPATHLEN);
754+
umem_free(realaltdir, MAXPATHLEN);
749755
}
750756
}
751757

@@ -762,10 +768,12 @@ ztest_random(uint64_t range)
762768
{
763769
uint64_t r;
764770

771+
ASSERT3S(ztest_fd_rand, >=, 0);
772+
765773
if (range == 0)
766774
return (0);
767775

768-
if (read(ZTEST_FD_RAND, &r, sizeof (r)) != sizeof (r))
776+
if (read(ztest_fd_rand, &r, sizeof (r)) != sizeof (r))
769777
fatal(1, "short read from /dev/urandom");
770778

771779
return (r % range);
@@ -5661,20 +5669,16 @@ ztest_init(ztest_shared_t *zs)
56615669
}
56625670

56635671
static void
5664-
setup_fds(void)
5672+
setup_data_fd(void)
56655673
{
5666-
int fd;
5674+
static char ztest_name_data[] = "/tmp/ztest.data.XXXXXX";
56675675

5668-
char *tmp = tempnam(NULL, NULL);
5669-
fd = open(tmp, O_RDWR | O_CREAT, 0700);
5670-
ASSERT3U(fd, ==, ZTEST_FD_DATA);
5671-
(void) unlink(tmp);
5672-
free(tmp);
5673-
5674-
fd = open("/dev/urandom", O_RDONLY);
5675-
ASSERT3U(fd, ==, ZTEST_FD_RAND);
5676+
ztest_fd_data = mkstemp(ztest_name_data);
5677+
ASSERT3S(ztest_fd_data, >=, 0);
5678+
(void) unlink(ztest_name_data);
56765679
}
56775680

5681+
56785682
static int
56795683
shared_data_size(ztest_shared_hdr_t *hdr)
56805684
{
@@ -5696,10 +5700,10 @@ setup_hdr(void)
56965700
ztest_shared_hdr_t *hdr;
56975701

56985702
hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()),
5699-
PROT_READ | PROT_WRITE, MAP_SHARED, ZTEST_FD_DATA, 0);
5703+
PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0);
57005704
ASSERT(hdr != MAP_FAILED);
57015705

5702-
VERIFY3U(0, ==, ftruncate(ZTEST_FD_DATA, sizeof (ztest_shared_hdr_t)));
5706+
VERIFY3U(0, ==, ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t)));
57035707

57045708
hdr->zh_hdr_size = sizeof (ztest_shared_hdr_t);
57055709
hdr->zh_opts_size = sizeof (ztest_shared_opts_t);
@@ -5710,7 +5714,7 @@ setup_hdr(void)
57105714
hdr->zh_ds_count = ztest_opts.zo_datasets;
57115715

57125716
size = shared_data_size(hdr);
5713-
VERIFY3U(0, ==, ftruncate(ZTEST_FD_DATA, size));
5717+
VERIFY3U(0, ==, ftruncate(ztest_fd_data, size));
57145718

57155719
(void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize()));
57165720
}
@@ -5723,14 +5727,14 @@ setup_data(void)
57235727
uint8_t *buf;
57245728

57255729
hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()),
5726-
PROT_READ, MAP_SHARED, ZTEST_FD_DATA, 0);
5730+
PROT_READ, MAP_SHARED, ztest_fd_data, 0);
57275731
ASSERT(hdr != MAP_FAILED);
57285732

57295733
size = shared_data_size(hdr);
57305734

57315735
(void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize()));
57325736
hdr = ztest_shared_hdr = (void *)mmap(0, P2ROUNDUP(size, getpagesize()),
5733-
PROT_READ | PROT_WRITE, MAP_SHARED, ZTEST_FD_DATA, 0);
5737+
PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0);
57345738
ASSERT(hdr != MAP_FAILED);
57355739
buf = (uint8_t *)hdr;
57365740

@@ -5749,12 +5753,13 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
57495753
{
57505754
pid_t pid;
57515755
int status;
5752-
char cmdbuf[MAXPATHLEN];
5756+
char *cmdbuf = NULL;
57535757

57545758
pid = fork();
57555759

57565760
if (cmd == NULL) {
5757-
(void) strlcpy(cmdbuf, getexecname(), sizeof (cmdbuf));
5761+
cmdbuf = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
5762+
(void) strlcpy(cmdbuf, getexecname(), MAXPATHLEN);
57585763
cmd = cmdbuf;
57595764
}
57605765

@@ -5763,9 +5768,16 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
57635768

57645769
if (pid == 0) { /* child */
57655770
char *emptyargv[2] = { cmd, NULL };
5771+
char fd_data_str[12];
57665772

57675773
struct rlimit rl = { 1024, 1024 };
57685774
(void) setrlimit(RLIMIT_NOFILE, &rl);
5775+
5776+
(void) close(ztest_fd_rand);
5777+
VERIFY3U(11, >=,
5778+
snprintf(fd_data_str, 12, "%d", ztest_fd_data));
5779+
VERIFY0(setenv("ZTEST_FD_DATA", fd_data_str, 1));
5780+
57695781
(void) enable_extended_FILE_stdio(-1, -1);
57705782
if (libpath != NULL)
57715783
VERIFY(0 == setenv("LD_LIBRARY_PATH", libpath, 1));
@@ -5774,6 +5786,11 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
57745786
fatal(B_TRUE, "exec failed: %s", cmd);
57755787
}
57765788

5789+
if (cmdbuf != NULL) {
5790+
umem_free(cmdbuf, MAXPATHLEN);
5791+
cmd = NULL;
5792+
}
5793+
57775794
while (waitpid(pid, &status, 0) != pid)
57785795
continue;
57795796
if (statusp != NULL)
@@ -5838,39 +5855,41 @@ main(int argc, char **argv)
58385855
char timebuf[100];
58395856
char numbuf[6];
58405857
spa_t *spa;
5841-
char cmd[MAXNAMELEN];
5858+
char *cmd;
58425859
boolean_t hasalt;
5843-
5844-
boolean_t ischild = (0 == lseek(ZTEST_FD_DATA, 0, SEEK_CUR));
5845-
ASSERT(ischild || errno == EBADF);
5860+
char *fd_data_str = getenv("ZTEST_FD_DATA");
58465861

58475862
(void) setvbuf(stdout, NULL, _IOLBF, 0);
58485863

58495864
dprintf_setup(&argc, argv);
58505865

5851-
if (!ischild) {
5866+
ztest_fd_rand = open("/dev/urandom", O_RDONLY);
5867+
ASSERT3S(ztest_fd_rand, >=, 0);
5868+
5869+
if (!fd_data_str) {
58525870
process_options(argc, argv);
58535871

5854-
setup_fds();
5872+
setup_data_fd();
58555873
setup_hdr();
58565874
setup_data();
58575875
bcopy(&ztest_opts, ztest_shared_opts,
58585876
sizeof (*ztest_shared_opts));
58595877
} else {
5878+
ztest_fd_data = atoi(fd_data_str);
58605879
setup_data();
58615880
bcopy(ztest_shared_opts, &ztest_opts, sizeof (ztest_opts));
58625881
}
58635882
ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count);
58645883

58655884
/* Override location of zpool.cache */
5866-
(void) asprintf((char **)&spa_config_path, "%s/zpool.cache",
5867-
ztest_opts.zo_dir);
5885+
VERIFY3U(asprintf((char **)&spa_config_path, "%s/zpool.cache",
5886+
ztest_opts.zo_dir), !=, -1);
58685887

58695888
ztest_ds = umem_alloc(ztest_opts.zo_datasets * sizeof (ztest_ds_t),
58705889
UMEM_NOFAIL);
58715890
zs = ztest_shared;
58725891

5873-
if (ischild) {
5892+
if (fd_data_str) {
58745893
metaslab_gang_bang = ztest_opts.zo_metaslab_gang_bang;
58755894
metaslab_df_alloc_threshold =
58765895
zs->zs_metaslab_df_alloc_threshold;
@@ -5893,7 +5912,8 @@ main(int argc, char **argv)
58935912
(u_longlong_t)ztest_opts.zo_time);
58945913
}
58955914

5896-
(void) strlcpy(cmd, getexecname(), sizeof (cmd));
5915+
cmd = umem_alloc(MAXNAMELEN, UMEM_NOFAIL);
5916+
(void) strlcpy(cmd, getexecname(), MAXNAMELEN);
58975917

58985918
zs->zs_do_init = B_TRUE;
58995919
if (strlen(ztest_opts.zo_alt_ztest) != 0) {
@@ -6034,5 +6054,7 @@ main(int argc, char **argv)
60346054
kills, iters - kills, (100.0 * kills) / MAX(1, iters));
60356055
}
60366056

6057+
umem_free(cmd, MAXNAMELEN);
6058+
60376059
return (0);
60386060
}

0 commit comments

Comments
 (0)