diff options
author | Chunwei Chen <[email protected]> | 2015-11-20 15:50:06 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2015-12-02 14:50:36 -0800 |
commit | 90aa094d6d77bf6f17a671ff76a84ae8232267d8 (patch) | |
tree | e5860ffa2cf16611b71e174edd04092628f918f6 /cmd | |
parent | b0fe1adeb1f24192c9a3358a4c9a29a34b9537fe (diff) |
Fix zdb calling behavior in ztest
The current zdb calling behaviour is really fragile, and is guaranteed to
segfault if ztest is not installed in either /sbin or /usr/sbin. With this
patch, the ztest will try to call zdb in the following order.
1. Use environmental variable ZDB_PATH if provided.
2. If ztest resides in build tree, guess the in tree zdb path.
3. Just pass zdb to popen and let it search it in PATH.
Signed-off-by: Chunwei Chen <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #3126
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/ztest/ztest.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index afe6faab0..1dc9eff77 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -5371,6 +5371,41 @@ ztest_spa_rename(ztest_ds_t *zd, uint64_t id) (void) rw_unlock(&ztest_name_lock); } +static int +ztest_check_path(char *path) +{ + struct stat s; + /* return true on success */ + return (!stat(path, &s)); +} + +static void +ztest_get_zdb_bin(char *bin, int len) +{ + char *zdb_path; + /* + * Try to use ZDB_PATH and in-tree zdb path. If not successful, just + * let popen to search through PATH. + */ + if ((zdb_path = getenv("ZDB_PATH"))) { + strlcpy(bin, zdb_path, len); /* In env */ + if (!ztest_check_path(bin)) { + ztest_dump_core = 0; + fatal(1, "invalid ZDB_PATH '%s'", bin); + } + return; + } + + VERIFY(realpath(getexecname(), bin) != NULL); + if (strstr(bin, "/ztest/")) { + strstr(bin, "/ztest/")[0] = '\0'; /* In-tree */ + strcat(bin, "/zdb/zdb"); + if (ztest_check_path(bin)) + return; + } + strcpy(bin, "zdb"); +} + /* * Verify pool integrity by running zdb. */ @@ -5381,21 +5416,14 @@ ztest_run_zdb(char *pool) char *bin; char *zdb; char *zbuf; + const int len = MAXPATHLEN + MAXNAMELEN + 20; FILE *fp; - bin = umem_alloc(MAXPATHLEN + MAXNAMELEN + 20, UMEM_NOFAIL); - zdb = umem_alloc(MAXPATHLEN + MAXNAMELEN + 20, UMEM_NOFAIL); + bin = umem_alloc(len, UMEM_NOFAIL); + zdb = umem_alloc(len, UMEM_NOFAIL); zbuf = umem_alloc(1024, UMEM_NOFAIL); - VERIFY(realpath(getexecname(), bin) != NULL); - if (strncmp(bin, "/usr/sbin/ztest", 15) == 0) { - strcpy(bin, "/usr/sbin/zdb"); /* Installed */ - } else if (strncmp(bin, "/sbin/ztest", 11) == 0) { - strcpy(bin, "/sbin/zdb"); /* Installed */ - } else { - strstr(bin, "/ztest/")[0] = '\0'; /* In-tree */ - strcat(bin, "/zdb/zdb"); - } + ztest_get_zdb_bin(bin, len); (void) sprintf(zdb, "%s -bcc%s%s -d -U %s %s", @@ -5425,8 +5453,8 @@ ztest_run_zdb(char *pool) else fatal(0, "'%s' died with signal %d", zdb, WTERMSIG(status)); out: - umem_free(bin, MAXPATHLEN + MAXNAMELEN + 20); - umem_free(zdb, MAXPATHLEN + MAXNAMELEN + 20); + umem_free(bin, len); + umem_free(zdb, len); umem_free(zbuf, 1024); } |