2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Eric Schrock <Eric.Schrock@delphix.com>

References:
  illumos/illumos-gate@53089ab7c8
  illumos/illumos-gate@ad135b5d64
  illumos changeset: 13700:2889e2596bd6
  https://www.illumos.org/issues/2619
  https://www.illumos.org/issues/2747

NOTE: The grub specific changes were not ported.  This change
must be made to the Linux grub packages.

Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
Christopher Siden
2012-12-13 15:24:15 -08:00
committed by Brian Behlendorf
parent 15313c5e18
commit 9ae529ec5d
67 changed files with 4267 additions and 467 deletions
+174 -30
View File
@@ -54,6 +54,7 @@
#include "zpool_util.h"
#include "zfs_comutil.h"
#include "zfeature_common.h"
#include "statcommon.h"
@@ -208,7 +209,7 @@ get_usage(zpool_help_t idx) {
case HELP_CLEAR:
return (gettext("\tclear [-nF] <pool> [device]\n"));
case HELP_CREATE:
return (gettext("\tcreate [-fn] [-o property=value] ... \n"
return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
"\t [-O file-system-property=value] ... \n"
"\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
case HELP_DESTROY:
@@ -341,6 +342,12 @@ usage(boolean_t requested)
/* Iterate over all properties */
(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
ZFS_TYPE_POOL);
(void) fprintf(fp, "\t%-15s ", "feature@...");
(void) fprintf(fp, "YES disabled | enabled | active\n");
(void) fprintf(fp, gettext("\nThe feature@ properties must be "
"appended with a feature name.\nSee zpool-features(5).\n"));
}
/*
@@ -407,12 +414,16 @@ add_prop_list(const char *propname, char *propval, nvlist_t **props,
proplist = *props;
if (poolprop) {
if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
!zpool_prop_feature(propname)) {
(void) fprintf(stderr, gettext("property '%s' is "
"not a valid pool property\n"), propname);
return (2);
}
normnm = zpool_prop_to_name(prop);
if (zpool_prop_feature(propname))
normnm = propname;
else
normnm = zpool_prop_to_name(prop);
} else {
if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
normnm = zfs_prop_to_name(fprop);
@@ -601,7 +612,7 @@ zpool_do_remove(int argc, char **argv)
}
/*
* zpool create [-fn] [-o property=value] ...
* zpool create [-fnd] [-o property=value] ...
* [-O file-system-property=value] ...
* [-R root] [-m mountpoint] <pool> <dev> ...
*
@@ -610,8 +621,10 @@ zpool_do_remove(int argc, char **argv)
* were to be created.
* -R Create a pool under an alternate root
* -m Set default mountpoint for the root dataset. By default it's
* '/<pool>'
* '/<pool>'
* -o Set property=value.
* -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
*
* Creates the named pool according to the given vdev specification. The
@@ -624,6 +637,7 @@ zpool_do_create(int argc, char **argv)
{
boolean_t force = B_FALSE;
boolean_t dryrun = B_FALSE;
boolean_t enable_all_pool_feat = B_TRUE;
int c;
nvlist_t *nvroot = NULL;
char *poolname;
@@ -635,7 +649,7 @@ zpool_do_create(int argc, char **argv)
char *propval;
/* check options */
while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) {
switch (c) {
case 'f':
force = B_TRUE;
@@ -643,6 +657,9 @@ zpool_do_create(int argc, char **argv)
case 'n':
dryrun = B_TRUE;
break;
case 'd':
enable_all_pool_feat = B_FALSE;
break;
case 'R':
altroot = optarg;
if (add_prop_list(zpool_prop_to_name(
@@ -670,6 +687,21 @@ zpool_do_create(int argc, char **argv)
if (add_prop_list(optarg, propval, &props, B_TRUE))
goto errout;
/*
* If the user is creating a pool that doesn't support
* feature flags, don't enable any features.
*/
if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
char *end;
u_longlong_t ver;
ver = strtoull(propval, &end, 10);
if (*end == '\0' &&
ver < SPA_VERSION_FEATURES) {
enable_all_pool_feat = B_FALSE;
}
}
break;
case 'O':
if ((propval = strchr(optarg, '=')) == NULL) {
@@ -735,7 +767,6 @@ zpool_do_create(int argc, char **argv)
goto errout;
}
if (altroot != NULL && altroot[0] != '/') {
(void) fprintf(stderr, gettext("invalid alternate root '%s': "
"must be an absolute path\n"), altroot);
@@ -817,6 +848,27 @@ zpool_do_create(int argc, char **argv)
/*
* Hand off to libzfs.
*/
if (enable_all_pool_feat) {
int 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);
/*
* Skip feature if user specified it manually
* on the command line.
*/
if (nvlist_exists(props, propname))
continue;
if (add_prop_list(propname, ZFS_FEATURE_ENABLED,
&props, B_TRUE) != 0)
goto errout;
}
}
if (zpool_create(g_zfs, poolname,
nvroot, props, fsprops) == 0) {
zfs_handle_t *pool = zfs_open(g_zfs, poolname,
@@ -1148,6 +1200,10 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
(void) printf(gettext("newer version"));
break;
case VDEV_AUX_UNSUP_FEAT:
(void) printf(gettext("unsupported feature(s)"));
break;
case VDEV_AUX_SPARED:
verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
&cb.cb_guid) == 0);
@@ -1265,6 +1321,10 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
(void) printf(gettext("newer version"));
break;
case VDEV_AUX_UNSUP_FEAT:
(void) printf(gettext("unsupported feature(s)"));
break;
case VDEV_AUX_ERR_EXCEEDED:
(void) printf(gettext("too many errors"));
break;
@@ -1431,6 +1491,20 @@ show_import(nvlist_t *config)
"incompatible version.\n"));
break;
case ZPOOL_STATUS_UNSUP_FEAT_READ:
(void) printf(gettext("status: The pool uses the following "
"feature(s) not supported on this sytem:\n"));
zpool_print_unsup_feat(config);
break;
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
(void) printf(gettext("status: The pool can only be accessed "
"in read-only mode on this system. It\n\tcannot be "
"accessed in read-write mode because it uses the "
"following\n\tfeature(s) not supported on this system:\n"));
zpool_print_unsup_feat(config);
break;
case ZPOOL_STATUS_HOSTID_MISMATCH:
(void) printf(gettext(" status: The pool was last accessed by "
"another system.\n"));
@@ -1488,6 +1562,20 @@ show_import(nvlist_t *config)
"newer\n\tsoftware, or recreate the pool from "
"backup.\n"));
break;
case ZPOOL_STATUS_UNSUP_FEAT_READ:
(void) printf(gettext("action: The pool cannot be "
"imported. Access the pool on a system that "
"supports\n\tthe required feature(s), or recreate "
"the pool from backup.\n"));
break;
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
(void) printf(gettext("action: The pool cannot be "
"imported in read-write mode. Import the pool "
"with\n"
"\t\"-o readonly=on\", access the pool on a system "
"that supports the\n\trequired feature(s), or "
"recreate the pool from backup.\n"));
break;
case ZPOOL_STATUS_MISSING_DEV_R:
case ZPOOL_STATUS_MISSING_DEV_NR:
case ZPOOL_STATUS_BAD_GUID_SUM:
@@ -1563,9 +1651,9 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
ZPOOL_CONFIG_POOL_STATE, &state) == 0);
verify(nvlist_lookup_uint64(config,
ZPOOL_CONFIG_VERSION, &version) == 0);
if (version > SPA_VERSION) {
if (!SPA_VERSION_IS_SUPPORTED(version)) {
(void) fprintf(stderr, gettext("cannot import '%s': pool "
"is formatted using a newer ZFS version\n"), name);
"is formatted using an unsupported ZFS version\n"), name);
return (1);
} else if (state != POOL_STATE_EXPORTED &&
!(flags & ZFS_IMPORT_ANY_HOST)) {
@@ -2556,15 +2644,13 @@ static void
print_header(list_cbdata_t *cb)
{
zprop_list_t *pl = cb->cb_proplist;
char headerbuf[ZPOOL_MAXPROPLEN];
const char *header;
boolean_t first = B_TRUE;
boolean_t right_justify;
size_t width = 0;
for (; pl != NULL; pl = pl->pl_next) {
if (pl->pl_prop == ZPROP_INVAL)
continue;
width = pl->pl_width;
if (first && cb->cb_verbose) {
/*
@@ -2579,8 +2665,18 @@ print_header(list_cbdata_t *cb)
else
first = B_FALSE;
header = zpool_prop_column_name(pl->pl_prop);
right_justify = zpool_prop_align_right(pl->pl_prop);
right_justify = B_FALSE;
if (pl->pl_prop != ZPROP_INVAL) {
header = zpool_prop_column_name(pl->pl_prop);
right_justify = zpool_prop_align_right(pl->pl_prop);
} else {
int i;
for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
headerbuf[i] = toupper(pl->pl_user_prop[i]);
headerbuf[i] = '\0';
header = headerbuf;
}
if (pl->pl_next == NULL && !right_justify)
(void) printf("%s", header);
@@ -2639,6 +2735,11 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
propstr = property;
right_justify = zpool_prop_align_right(pl->pl_prop);
} else if ((zpool_prop_feature(pl->pl_user_prop) ||
zpool_prop_unsupported(pl->pl_user_prop)) &&
zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
sizeof (property)) == 0) {
propstr = property;
} else {
propstr = "-";
}
@@ -3958,6 +4059,31 @@ status_callback(zpool_handle_t *zhp, void *data)
"backup.\n"));
break;
case ZPOOL_STATUS_UNSUP_FEAT_READ:
(void) printf(gettext("status: The pool cannot be accessed on "
"this system because it uses the\n\tfollowing feature(s) "
"not supported on this system:\n"));
zpool_print_unsup_feat(config);
(void) printf("\n");
(void) printf(gettext("action: Access the pool from a system "
"that supports the required feature(s),\n\tor restore the "
"pool from backup.\n"));
break;
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
(void) printf(gettext("status: The pool can only be accessed "
"in read-only mode on this system. It\n\tcannot be "
"accessed in read-write mode because it uses the "
"following\n\tfeature(s) not supported on this system:\n"));
zpool_print_unsup_feat(config);
(void) printf("\n");
(void) printf(gettext("action: The pool cannot be accessed in "
"read-write mode. Import the pool with\n"
"\t\"-o readonly=on\", access the pool from a system that "
"supports the\n\trequired feature(s), or restore the "
"pool from backup.\n"));
break;
case ZPOOL_STATUS_FAULTED_DEV_R:
(void) printf(gettext("status: One or more devices are "
"faulted in response to persistent errors.\n\tSufficient "
@@ -4182,7 +4308,8 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
&version) == 0);
if (!cbp->cb_newer && version < SPA_VERSION) {
if (!cbp->cb_newer && SPA_VERSION_IS_SUPPORTED(version) &&
version != SPA_VERSION) {
if (!cbp->cb_all) {
if (cbp->cb_first) {
(void) printf(gettext("The following pools are "
@@ -4205,13 +4332,14 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
"'%s'\n\n"), zpool_get_name(zhp));
}
}
} else if (cbp->cb_newer && version > SPA_VERSION) {
} else if (cbp->cb_newer && !SPA_VERSION_IS_SUPPORTED(version)) {
assert(!cbp->cb_all);
if (cbp->cb_first) {
(void) printf(gettext("The following pools are "
"formatted using a newer software version and\n"
"cannot be accessed on the current system.\n\n"));
"formatted using an unsupported software version "
"and\ncannot be accessed on the current "
"system.\n\n"));
(void) printf(gettext("VER POOL\n"));
(void) printf(gettext("--- ------------\n"));
cbp->cb_first = B_FALSE;
@@ -4295,8 +4423,8 @@ zpool_do_upgrade(int argc, char **argv)
break;
case 'V':
cb.cb_version = strtoll(optarg, &end, 10);
if (*end != '\0' || cb.cb_version > SPA_VERSION ||
cb.cb_version < SPA_VERSION_1) {
if (*end != '\0' ||
!SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
(void) fprintf(stderr,
gettext("invalid version '%s'\n"), optarg);
usage(B_FALSE);
@@ -4341,8 +4469,8 @@ zpool_do_upgrade(int argc, char **argv)
}
}
(void) printf(gettext("This system is currently running "
"ZFS pool version %llu.\n\n"), SPA_VERSION);
(void) printf(gettext("This system supports ZFS pool feature "
"flags.\n\n"));
cb.cb_first = B_TRUE;
if (showversions) {
(void) printf(gettext("The following versions are "
@@ -4923,13 +5051,26 @@ get_callback(zpool_handle_t *zhp, void *data)
pl == cbp->cb_proplist)
continue;
if (zpool_get_prop(zhp, pl->pl_prop,
value, sizeof (value), &srctype) != 0)
continue;
if (pl->pl_prop == ZPROP_INVAL &&
(zpool_prop_feature(pl->pl_user_prop) ||
zpool_prop_unsupported(pl->pl_user_prop))) {
srctype = ZPROP_SRC_LOCAL;
zprop_print_one_property(zpool_get_name(zhp), cbp,
zpool_prop_to_name(pl->pl_prop), value, srctype, NULL,
NULL);
if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
value, sizeof (value)) == 0) {
zprop_print_one_property(zpool_get_name(zhp),
cbp, pl->pl_user_prop, value, srctype,
NULL, NULL);
}
} else {
if (zpool_get_prop(zhp, pl->pl_prop, value,
sizeof (value), &srctype) != 0)
continue;
zprop_print_one_property(zpool_get_name(zhp), cbp,
zpool_prop_to_name(pl->pl_prop), value, srctype,
NULL, NULL);
}
}
return (0);
}
@@ -4941,8 +5082,11 @@ zpool_do_get(int argc, char **argv)
zprop_list_t fake_name = { 0 };
int ret;
if (argc < 3)
if (argc < 2) {
(void) fprintf(stderr, gettext("missing property "
"argument\n"));
usage(B_FALSE);
}
cb.cb_first = B_TRUE;
cb.cb_sources = ZPROP_SRC_ALL;
@@ -4952,7 +5096,7 @@ zpool_do_get(int argc, char **argv)
cb.cb_columns[3] = GET_COL_SOURCE;
cb.cb_type = ZFS_TYPE_POOL;
if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
ZFS_TYPE_POOL) != 0)
usage(B_FALSE);