aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zpool/zpool_iter.c30
-rw-r--r--cmd/zpool/zpool_main.c32
-rw-r--r--cmd/zpool/zpool_util.h12
-rw-r--r--tests/runfiles/linux.run3
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh23
5 files changed, 81 insertions, 19 deletions
diff --git a/cmd/zpool/zpool_iter.c b/cmd/zpool/zpool_iter.c
index 1d376d4fb..8d8dc1731 100644
--- a/cmd/zpool/zpool_iter.c
+++ b/cmd/zpool/zpool_iter.c
@@ -360,7 +360,7 @@ for_each_vdev_run_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_vcdl)
vdev_cmd_data_list_t *vcdl = cb_vcdl;
vdev_cmd_data_t *data;
char *path = NULL;
- int i;
+ int i, match = 0;
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
return (1);
@@ -374,6 +374,19 @@ for_each_vdev_run_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_vcdl)
}
}
+ /* Check for whitelisted vdevs here, if any */
+ for (i = 0; i < vcdl->vdev_names_count; i++) {
+ if (strcmp(vcdl->vdev_names[i], zpool_vdev_name(g_zfs, zhp, nv,
+ vcdl->cb_name_flags)) == 0) {
+ match = 1;
+ break; /* match */
+ }
+ }
+
+ /* If we whitelisted vdevs, and this isn't one of them, then bail out */
+ if (!match && vcdl->vdev_names_count)
+ return (0);
+
/*
* Resize our array and add in the new element.
*/
@@ -437,19 +450,28 @@ all_pools_for_each_vdev_run_vcdl(vdev_cmd_data_list_t *vcdl)
}
/*
- * Run command 'cmd' on all vdevs in all pools. Saves the first line of output
- * from the command in vcdk->data[].line for all vdevs.
+ * Run command 'cmd' on all vdevs in all pools in argv. Saves the first line of
+ * output from the command in vcdk->data[].line for all vdevs. If you want
+ * to run the command on only certain vdevs, fill in g_zfs, vdev_names,
+ * vdev_names_count, and cb_name_flags. Otherwise leave them as zero.
*
* Returns a vdev_cmd_data_list_t that must be freed with
* free_vdev_cmd_data_list();
*/
vdev_cmd_data_list_t *
-all_pools_for_each_vdev_run(int argc, char **argv, char *cmd)
+all_pools_for_each_vdev_run(int argc, char **argv, char *cmd,
+ libzfs_handle_t *g_zfs, char **vdev_names, int vdev_names_count,
+ int cb_name_flags)
{
vdev_cmd_data_list_t *vcdl;
vcdl = safe_malloc(sizeof (vdev_cmd_data_list_t));
vcdl->cmd = cmd;
+ vcdl->vdev_names = vdev_names;
+ vcdl->vdev_names_count = vdev_names_count;
+ vcdl->cb_name_flags = cb_name_flags;
+ vcdl->g_zfs = g_zfs;
+
/* Gather our list of all vdevs in all pools */
for_each_pool(argc, argv, B_TRUE, NULL,
all_pools_for_each_vdev_gather_cb, vcdl);
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index a8233e336..f5740c00e 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -312,7 +312,7 @@ get_usage(zpool_help_t idx) {
"[-R root] [-F [-n]]\n"
"\t <pool | id> [newpool]\n"));
case HELP_IOSTAT:
- return (gettext("\tiostat [-T d | u] [-ghHLpPvy] "
+ return (gettext("\tiostat [-c CMD] [-T d | u] [-ghHLpPvy] "
"[[-lq]|[-r|-w]]\n"
"\t [[pool ...]|[pool vdev ...]|[vdev ...]] "
"[interval [count]]\n"));
@@ -335,8 +335,8 @@ get_usage(zpool_help_t idx) {
case HELP_SCRUB:
return (gettext("\tscrub [-s] <pool> ...\n"));
case HELP_STATUS:
- return (gettext("\tstatus [-gLPvxD] [-T d|u] [pool] ... "
- "[interval [count]]\n"));
+ return (gettext("\tstatus [-c CMD] [-gLPvxD] [-T d|u] [pool]"
+ " ... [interval [count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade\n"
"\tupgrade -v\n"
@@ -4055,8 +4055,13 @@ zpool_do_iostat(int argc, char **argv)
usage(B_FALSE);
break;
case '?':
- (void) fprintf(stderr, gettext("invalid option '%c'\n"),
- optopt);
+ if (optopt == 'c') {
+ fprintf(stderr,
+ gettext("Missing CMD for -c\n"));
+ } else {
+ fprintf(stderr,
+ gettext("invalid option '%c'\n"), optopt);
+ }
usage(B_FALSE);
}
}
@@ -4256,9 +4261,10 @@ zpool_do_iostat(int argc, char **argv)
continue;
}
- if (cmd != NULL)
+ if (cmd != NULL && cb.cb_verbose)
cb.vcdl = all_pools_for_each_vdev_run(argc,
- argv, cmd);
+ argv, cmd, g_zfs, cb.cb_vdev_names,
+ cb.cb_vdev_names_count, cb.cb_name_flags);
pool_list_iter(list, B_FALSE, print_iostat, &cb);
@@ -6113,8 +6119,13 @@ zpool_do_status(int argc, char **argv)
get_timestamp_arg(*optarg);
break;
case '?':
- (void) fprintf(stderr, gettext("invalid option '%c'\n"),
- optopt);
+ if (optopt == 'c') {
+ fprintf(stderr,
+ gettext("Missing CMD for -c\n"));
+ } else {
+ fprintf(stderr,
+ gettext("invalid option '%c'\n"), optopt);
+ }
usage(B_FALSE);
}
}
@@ -6135,7 +6146,8 @@ zpool_do_status(int argc, char **argv)
print_timestamp(timestamp_fmt);
if (cmd != NULL)
- cb.vcdl = all_pools_for_each_vdev_run(argc, argv, cmd);
+ cb.vcdl = all_pools_for_each_vdev_run(argc, argv, cmd,
+ NULL, NULL, 0, 0);
ret = for_each_pool(argc, argv, B_TRUE, NULL,
status_callback, &cb);
diff --git a/cmd/zpool/zpool_util.h b/cmd/zpool/zpool_util.h
index 0d83b54d5..acdfd5075 100644
--- a/cmd/zpool/zpool_util.h
+++ b/cmd/zpool/zpool_util.h
@@ -86,11 +86,21 @@ typedef struct vdev_cmd_data_list
{
char *cmd; /* Command to run */
unsigned int count; /* Number of vdev_cmd_data items (vdevs) */
+
+ /* vars to whitelist only certain vdevs, if requested */
+ libzfs_handle_t *g_zfs;
+ char **vdev_names;
+ int vdev_names_count;
+ int cb_name_flags;
+
vdev_cmd_data_t *data; /* Array of vdevs */
+
} vdev_cmd_data_list_t;
vdev_cmd_data_list_t *all_pools_for_each_vdev_run(int argc, char **argv,
- char *cmd);
+ char *cmd, libzfs_handle_t *g_zfs, char **vdev_names, int vdev_names_count,
+ int cb_name_flags);
+
void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl);
#ifdef __cplusplus
diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
index 4dd444035..5d146c6bd 100644
--- a/tests/runfiles/linux.run
+++ b/tests/runfiles/linux.run
@@ -362,7 +362,8 @@ user =
[tests/functional/cli_user/zpool_iostat]
tests = ['zpool_iostat_001_neg', 'zpool_iostat_002_pos',
- 'zpool_iostat_003_neg', 'zpool_iostat_004_pos']
+ 'zpool_iostat_003_neg', 'zpool_iostat_004_pos',
+ 'zpool_iostat_005_pos']
user =
[tests/functional/cli_user/zpool_list]
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
index be38933c1..89a9a4975 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
@@ -54,10 +54,27 @@ fi
# a '/' when we specify the path (-P) flag. We check for "{}" to see if one
# of the VDEV variables isn't set.
#
-C1=$($ZPOOL iostat -Pv | $GREP -E '^\s+/' | $WC -l)
-C2=$($ZPOOL iostat -Pv -c 'echo vdev_test{$VDEV_PATH}{$VDEV_UPATH}' | $GREP -E '^\s+/' | $GREP -v '{}' | $WC -l)
+C1=$($ZPOOL iostat -Pv $testpool | $GREP -E '^\s+/' | $WC -l)
+C2=$($ZPOOL iostat -Pv -c 'echo vdev_test{$VDEV_PATH}{$VDEV_UPATH}' $testpool \
+ | $GREP -E '^\s+/' | $GREP -v '{}' | $WC -l)
if [ "$C1" != "$C2" ] ; then
log_fail "zpool iostat -c failed, expected $C1 vdevs, got $C2"
else
- log_pass "zpool iostat -c passed, expected $C1 vdevs, got $C2"
+ log_note "zpool iostat -c passed, expected $C1 vdevs, got $C2"
+fi
+
+# Call iostat on only a specific vdev, and verify that the command only gets
+# run on the vdev. We write the command results to a temp file to verify that
+# the command actually gets run, rather than just verifying that the results
+# are *displayed* for the specific vdev.
+TMP=$($MKTEMP)
+FIRST_VDEV=$($ZPOOL iostat -Pv $testpool | $GREP -Eo '^\s+/[^ ]+' | $HEAD -n 1)
+log_must $ZPOOL iostat -Pv -c "echo \$VDEV_PATH >> $TMP" $testpool \
+ $FIRST_VDEV > /dev/null
+C2=$($WC -w < $TMP)
+$RM $TMP
+if [ "$C2" != "1" ] ; then
+ log_fail "zpool iostat -c <VDEV> failed, expected 1 vdev, got $C2"
+else
+ log_note "zpool iostat -c <VDEV> passed, expected 1 vdev, got $C2"
fi