mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
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:
committed by
Brian Behlendorf
parent
15313c5e18
commit
9ae529ec5d
+174
-30
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user