diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 3431ec67a0a7..b6702f22c099 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -920,6 +920,7 @@ zpool_do_labelclear(int argc, char **argv) * -m Set default mountpoint for the root dataset. By default it's * '/' * -o Set property=value. + * -o Set feature@feature=enabled|disabled. * -d Don't automatically enable all supported pool features * (individual features can be enabled with -o). * -O Set fsproperty=value in the pool's root file system @@ -1188,22 +1189,26 @@ zpool_do_create(int argc, char **argv) /* * Hand off to libzfs. */ - if (enable_all_pool_feat) { - spa_feature_t i; - for (i = 0; i < SPA_FEATURES; i++) { - char propname[MAXPATHLEN]; - zfeature_info_t *feat = &spa_feature_table[i]; - - (void) snprintf(propname, sizeof (propname), - "feature@%s", feat->fi_uname); + spa_feature_t i; + for (i = 0; i < SPA_FEATURES; i++) { + char propname[MAXPATHLEN]; + char *propval; + zfeature_info_t *feat = &spa_feature_table[i]; - /* - * Skip feature if user specified it manually - * on the command line. - */ - if (nvlist_exists(props, propname)) - continue; + (void) snprintf(propname, sizeof (propname), + "feature@%s", feat->fi_uname); + /* + * Only features contained in props will be enabled: + * remove from the nvlist every ZFS_FEATURE_DISABLED + * value and add every missing ZFS_FEATURE_ENABLED if + * enable_all_pool_feat is set. + */ + if (!nvlist_lookup_string(props, propname, &propval)) { + if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0) + (void) nvlist_remove_all(props, + propname); + } else if (enable_all_pool_feat) { ret = add_prop_list(propname, ZFS_FEATURE_ENABLED, &props, B_TRUE); if (ret != 0) diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 0641c18449dd..6727a77e79ea 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -502,10 +502,11 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, } (void) nvpair_value_string(elem, &strval); - if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) { + if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0 && + strcmp(strval, ZFS_FEATURE_DISABLED) != 0) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "property '%s' can only be set to " - "'enabled'"), propname); + "'enabled' or 'disabled'"), propname); (void) zfs_error(hdl, EZFS_BADPROP, errbuf); goto error; } diff --git a/man/man8/zpool.8 b/man/man8/zpool.8 index 3518175699f8..43dccc05a3ef 100644 --- a/man/man8/zpool.8 +++ b/man/man8/zpool.8 @@ -41,8 +41,9 @@ zpool \- configures ZFS storage pools .LP .nf -\fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-O\fR \fIfile-system-property=value\fR] - ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] [\fB-t\fR \fItname\fR] \fIpool\fR \fIvdev\fR ... +\fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-o\fR feature@\fIfeature=value\fR] + ... [\fB-O\fR \fIfile-system-property=value\fR] ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] + ... [\fB-t\fR \fItname\fR] \fIpool\fR \fIvdev\fR ... .fi .LP @@ -877,7 +878,7 @@ Clears device errors in a pool. If no arguments are specified, all device errors .sp .ne 2 .na -\fB\fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-O\fR \fIfile-system-property=value\fR] ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] [\fB-t\fR \fItname\fR] \fIpool\fR \fIvdev\fR ...\fR +\fB\fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-o\fR feature@\fIfeature=value\fR] ... [\fB-O\fR \fIfile-system-property=value\fR] ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] [\fB-t\fR \fItname\fR] \fIpool\fR \fIvdev\fR ...\fR .ad .sp .6 .RS 4n @@ -930,6 +931,18 @@ Do not enable any features on the new pool. Individual features can be enabled b Sets the given pool properties. See the "Properties" section for a list of valid properties that can be set. .RE +.sp +.ne 2 +.na +\fB\fB-o\fR feature@\fIfeature=value\fR [\fB-o\fR feature@\fIfeature=value\fR] ...\fR +.ad +.sp .6 +.RS 4n +Sets the given pool feature. See \fBzpool-features(5)\fR for a list of valid features that can be set. +.sp +Value can be either \fBdisabled\fR or \fBenabled\fR. +.RE + .sp .ne 2 .na diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run index bfda141f541b..9d63d68535cb 100644 --- a/tests/runfiles/linux.run +++ b/tests/runfiles/linux.run @@ -250,7 +250,8 @@ tests = [ 'zpool_create_021_pos', 'zpool_create_022_pos', 'zpool_create_023_neg', 'zpool_create_024_pos', 'zpool_create_features_001_pos', 'zpool_create_features_002_pos', - 'zpool_create_features_003_pos', 'zpool_create_features_004_neg'] + 'zpool_create_features_003_pos', 'zpool_create_features_004_neg', + 'zpool_create_features_005_pos'] # DISABLED: # zpool_destroy_001_pos - failure should be investigated diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am index a9ffbee03aba..8cfc5bd00231 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am @@ -30,4 +30,5 @@ dist_pkgdata_SCRIPTS = \ zpool_create_features_001_pos.ksh \ zpool_create_features_002_pos.ksh \ zpool_create_features_003_pos.ksh \ - zpool_create_features_004_neg.ksh + zpool_create_features_004_neg.ksh \ + zpool_create_features_005_pos.ksh diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh index a52e86251df6..2b465d5a41e2 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh @@ -39,7 +39,7 @@ verify_runnable "global" properties="\ -feature@async_destroy=disabled \ +feature@async_destroy=disable \ feature@async_destroy=active \ feature@xxx_fake_xxx=enabled \ unsupported@some_feature=inactive \ diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh new file mode 100755 index 000000000000..488f11c9b7c3 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh @@ -0,0 +1,93 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2012 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib + +################################################################################ +# +# Specifically disabling a feature, all other features should be enabled. +# +# 1. Loop through all existing features: +# a. Create a new pool with '-o feature@XXX=disabled'. +# b. Verify that every other feature is 'enabled' or 'active'. +# +################################################################################ + +verify_runnable "global" + +function cleanup +{ + datasetexists $TESTPOOL && log_must $ZPOOL destroy $TESTPOOL +} + +function check_features +{ + typeset feature="${1}" + + ${ZPOOL} get all ${TESTPOOL} | $GREP feature@ | while read line; do + set -- $(echo "${line}") + + if [[ "feature@${feature}" == "${2}" ]]; then + # Failure passed feature must be disabled. + if [[ "${3}" != "disabled" ]]; then + return 1; + fi + else + # Failure other features must be enabled or active. + if [[ "${3}" != "enabled" && "${3}" != "active" ]]; then + return 2; + fi + fi + done + + # All features enabled or active except the expected one. + return 0 +} + +log_onexit cleanup + +# Several representative features are tested to keep the test time short. +# The features 'extensible_dataset' and 'enabled_txg' are intentionally +# excluded because other features depend on them. +set -A features \ + "hole_birth" \ + "large_blocks" \ + "large_dnode" \ + "userobj_accounting" + +typeset -i i=0 +while (( $i < ${#features[*]} )); do + log_assert "'zpool create' creates pools with ${features[i]} disabled" + + log_must $ZPOOL create -f -o "feature@${features[i]}=disabled" \ + $TESTPOOL $DISKS + log_must check_features "${features[i]}" + log_must $ZPOOL destroy -f $TESTPOOL + (( i = i+1 )) +done + +log_pass "'zpool create -o feature@feature=disabled' disables features"