mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-25 18:59:33 +03:00
Illumos #3349: zpool upgrade -V bumps the on disk version number
3349 zpool upgrade -V bumps the on disk version number, but leaves the in core version Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Christopher Siden <chris.siden@delphix.com> Reviewed by: Matt Ahrens <matthew.ahrens@delphix.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Approved by: Dan McDonald <danmcd@nexenta.com> References: illumos/illumos-gate@25345e4666 https://www.illumos.org/issues/3349 Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
29809a6cba
commit
ea0b2538cd
@ -331,6 +331,7 @@ ztest_func_t ztest_vdev_add_remove;
|
|||||||
ztest_func_t ztest_vdev_aux_add_remove;
|
ztest_func_t ztest_vdev_aux_add_remove;
|
||||||
ztest_func_t ztest_split_pool;
|
ztest_func_t ztest_split_pool;
|
||||||
ztest_func_t ztest_reguid;
|
ztest_func_t ztest_reguid;
|
||||||
|
ztest_func_t ztest_spa_upgrade;
|
||||||
|
|
||||||
uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */
|
uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */
|
||||||
uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
|
uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
|
||||||
@ -364,6 +365,7 @@ ztest_info_t ztest_info[] = {
|
|||||||
{ ztest_reguid, 1, &zopt_sometimes },
|
{ ztest_reguid, 1, &zopt_sometimes },
|
||||||
{ ztest_spa_rename, 1, &zopt_rarely },
|
{ ztest_spa_rename, 1, &zopt_rarely },
|
||||||
{ ztest_scrub, 1, &zopt_rarely },
|
{ ztest_scrub, 1, &zopt_rarely },
|
||||||
|
{ ztest_spa_upgrade, 1, &zopt_rarely },
|
||||||
{ ztest_dsl_dataset_promote_busy, 1, &zopt_rarely },
|
{ ztest_dsl_dataset_promote_busy, 1, &zopt_rarely },
|
||||||
{ ztest_vdev_attach_detach, 1, &zopt_rarely },
|
{ ztest_vdev_attach_detach, 1, &zopt_rarely },
|
||||||
{ ztest_vdev_LUN_growth, 1, &zopt_rarely },
|
{ ztest_vdev_LUN_growth, 1, &zopt_rarely },
|
||||||
@ -818,7 +820,7 @@ ztest_get_ashift(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
|
make_vdev_file(char *path, char *aux, char *pool, size_t size, uint64_t ashift)
|
||||||
{
|
{
|
||||||
char *pathbuf;
|
char *pathbuf;
|
||||||
uint64_t vdev;
|
uint64_t vdev;
|
||||||
@ -836,12 +838,13 @@ make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
|
|||||||
vdev = ztest_shared->zs_vdev_aux;
|
vdev = ztest_shared->zs_vdev_aux;
|
||||||
(void) snprintf(path, MAXPATHLEN,
|
(void) snprintf(path, MAXPATHLEN,
|
||||||
ztest_aux_template, ztest_opts.zo_dir,
|
ztest_aux_template, ztest_opts.zo_dir,
|
||||||
ztest_opts.zo_pool, aux, vdev);
|
pool == NULL ? ztest_opts.zo_pool : pool,
|
||||||
|
aux, vdev);
|
||||||
} else {
|
} else {
|
||||||
vdev = ztest_shared->zs_vdev_next_leaf++;
|
vdev = ztest_shared->zs_vdev_next_leaf++;
|
||||||
(void) snprintf(path, MAXPATHLEN,
|
(void) snprintf(path, MAXPATHLEN,
|
||||||
ztest_dev_template, ztest_opts.zo_dir,
|
ztest_dev_template, ztest_opts.zo_dir,
|
||||||
ztest_opts.zo_pool, vdev);
|
pool == NULL ? ztest_opts.zo_pool : pool, vdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,17 +867,18 @@ make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
make_vdev_raidz(char *path, char *aux, size_t size, uint64_t ashift, int r)
|
make_vdev_raidz(char *path, char *aux, char *pool, size_t size,
|
||||||
|
uint64_t ashift, int r)
|
||||||
{
|
{
|
||||||
nvlist_t *raidz, **child;
|
nvlist_t *raidz, **child;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (r < 2)
|
if (r < 2)
|
||||||
return (make_vdev_file(path, aux, size, ashift));
|
return (make_vdev_file(path, aux, pool, size, ashift));
|
||||||
child = umem_alloc(r * sizeof (nvlist_t *), UMEM_NOFAIL);
|
child = umem_alloc(r * sizeof (nvlist_t *), UMEM_NOFAIL);
|
||||||
|
|
||||||
for (c = 0; c < r; c++)
|
for (c = 0; c < r; c++)
|
||||||
child[c] = make_vdev_file(path, aux, size, ashift);
|
child[c] = make_vdev_file(path, aux, pool, size, ashift);
|
||||||
|
|
||||||
VERIFY(nvlist_alloc(&raidz, NV_UNIQUE_NAME, 0) == 0);
|
VERIFY(nvlist_alloc(&raidz, NV_UNIQUE_NAME, 0) == 0);
|
||||||
VERIFY(nvlist_add_string(raidz, ZPOOL_CONFIG_TYPE,
|
VERIFY(nvlist_add_string(raidz, ZPOOL_CONFIG_TYPE,
|
||||||
@ -893,19 +897,19 @@ make_vdev_raidz(char *path, char *aux, size_t size, uint64_t ashift, int r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
make_vdev_mirror(char *path, char *aux, size_t size, uint64_t ashift,
|
make_vdev_mirror(char *path, char *aux, char *pool, size_t size,
|
||||||
int r, int m)
|
uint64_t ashift, int r, int m)
|
||||||
{
|
{
|
||||||
nvlist_t *mirror, **child;
|
nvlist_t *mirror, **child;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (m < 1)
|
if (m < 1)
|
||||||
return (make_vdev_raidz(path, aux, size, ashift, r));
|
return (make_vdev_raidz(path, aux, pool, size, ashift, r));
|
||||||
|
|
||||||
child = umem_alloc(m * sizeof (nvlist_t *), UMEM_NOFAIL);
|
child = umem_alloc(m * sizeof (nvlist_t *), UMEM_NOFAIL);
|
||||||
|
|
||||||
for (c = 0; c < m; c++)
|
for (c = 0; c < m; c++)
|
||||||
child[c] = make_vdev_raidz(path, aux, size, ashift, r);
|
child[c] = make_vdev_raidz(path, aux, pool, size, ashift, r);
|
||||||
|
|
||||||
VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0);
|
VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0);
|
||||||
VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE,
|
VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE,
|
||||||
@ -922,8 +926,8 @@ make_vdev_mirror(char *path, char *aux, size_t size, uint64_t ashift,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
make_vdev_root(char *path, char *aux, size_t size, uint64_t ashift,
|
make_vdev_root(char *path, char *aux, char *pool, size_t size, uint64_t ashift,
|
||||||
int log, int r, int m, int t)
|
int log, int r, int m, int t)
|
||||||
{
|
{
|
||||||
nvlist_t *root, **child;
|
nvlist_t *root, **child;
|
||||||
int c;
|
int c;
|
||||||
@ -933,7 +937,8 @@ make_vdev_root(char *path, char *aux, size_t size, uint64_t ashift,
|
|||||||
child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL);
|
child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL);
|
||||||
|
|
||||||
for (c = 0; c < t; c++) {
|
for (c = 0; c < t; c++) {
|
||||||
child[c] = make_vdev_mirror(path, aux, size, ashift, r, m);
|
child[c] = make_vdev_mirror(path, aux, pool, size, ashift,
|
||||||
|
r, m);
|
||||||
VERIFY(nvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
|
VERIFY(nvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
|
||||||
log) == 0);
|
log) == 0);
|
||||||
}
|
}
|
||||||
@ -951,6 +956,27 @@ make_vdev_root(char *path, char *aux, size_t size, uint64_t ashift,
|
|||||||
return (root);
|
return (root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a random spa version. Returns back a random spa version in the
|
||||||
|
* range [initial_version, SPA_VERSION_FEATURES].
|
||||||
|
*/
|
||||||
|
static uint64_t
|
||||||
|
ztest_random_spa_version(uint64_t initial_version)
|
||||||
|
{
|
||||||
|
uint64_t version = initial_version;
|
||||||
|
|
||||||
|
if (version <= SPA_VERSION_BEFORE_FEATURES) {
|
||||||
|
version = version +
|
||||||
|
ztest_random(SPA_VERSION_BEFORE_FEATURES - version + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version > SPA_VERSION_BEFORE_FEATURES)
|
||||||
|
version = SPA_VERSION_FEATURES;
|
||||||
|
|
||||||
|
ASSERT(SPA_VERSION_IS_SUPPORTED(version));
|
||||||
|
return (version);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ztest_random_blocksize(void)
|
ztest_random_blocksize(void)
|
||||||
{
|
{
|
||||||
@ -2306,7 +2332,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
/*
|
/*
|
||||||
* Attempt to create using a bad file.
|
* Attempt to create using a bad file.
|
||||||
*/
|
*/
|
||||||
nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 0, 1);
|
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
|
||||||
VERIFY3U(ENOENT, ==,
|
VERIFY3U(ENOENT, ==,
|
||||||
spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL));
|
spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL));
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
@ -2314,7 +2340,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
/*
|
/*
|
||||||
* Attempt to create using a bad mirror.
|
* Attempt to create using a bad mirror.
|
||||||
*/
|
*/
|
||||||
nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 2, 1);
|
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 2, 1);
|
||||||
VERIFY3U(ENOENT, ==,
|
VERIFY3U(ENOENT, ==,
|
||||||
spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL));
|
spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL));
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
@ -2324,7 +2350,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
* what's in the nvroot; we should fail with EEXIST.
|
* what's in the nvroot; we should fail with EEXIST.
|
||||||
*/
|
*/
|
||||||
(void) rw_enter(&ztest_name_lock, RW_READER);
|
(void) rw_enter(&ztest_name_lock, RW_READER);
|
||||||
nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 0, 1);
|
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
|
||||||
VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL));
|
VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL));
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
|
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
|
||||||
@ -2334,6 +2360,78 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
(void) rw_exit(&ztest_name_lock);
|
(void) rw_exit(&ztest_name_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
|
||||||
|
{
|
||||||
|
spa_t *spa;
|
||||||
|
uint64_t initial_version = SPA_VERSION_INITIAL;
|
||||||
|
uint64_t version, newversion;
|
||||||
|
nvlist_t *nvroot, *props;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
mutex_enter(&ztest_vdev_lock);
|
||||||
|
name = kmem_asprintf("%s_upgrade", ztest_opts.zo_pool);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up from previous runs.
|
||||||
|
*/
|
||||||
|
(void) spa_destroy(name);
|
||||||
|
|
||||||
|
nvroot = make_vdev_root(NULL, NULL, name, ztest_opts.zo_vdev_size, 0,
|
||||||
|
0, ztest_opts.zo_raidz, ztest_opts.zo_mirrors, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're configuring a RAIDZ device then make sure that the
|
||||||
|
* the initial version is capable of supporting that feature.
|
||||||
|
*/
|
||||||
|
switch (ztest_opts.zo_raidz_parity) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
initial_version = SPA_VERSION_INITIAL;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
initial_version = SPA_VERSION_RAIDZ2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
initial_version = SPA_VERSION_RAIDZ3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a pool with a spa version that can be upgraded. Pick
|
||||||
|
* a value between initial_version and SPA_VERSION_BEFORE_FEATURES.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
version = ztest_random_spa_version(initial_version);
|
||||||
|
} while (version > SPA_VERSION_BEFORE_FEATURES);
|
||||||
|
|
||||||
|
props = fnvlist_alloc();
|
||||||
|
fnvlist_add_uint64(props,
|
||||||
|
zpool_prop_to_name(ZPOOL_PROP_VERSION), version);
|
||||||
|
VERIFY3S(spa_create(name, nvroot, props, NULL, NULL), ==, 0);
|
||||||
|
fnvlist_free(nvroot);
|
||||||
|
fnvlist_free(props);
|
||||||
|
|
||||||
|
VERIFY3S(spa_open(name, &spa, FTAG), ==, 0);
|
||||||
|
VERIFY3U(spa_version(spa), ==, version);
|
||||||
|
newversion = ztest_random_spa_version(version + 1);
|
||||||
|
|
||||||
|
if (ztest_opts.zo_verbose >= 4) {
|
||||||
|
(void) printf("upgrading spa version from %llu to %llu\n",
|
||||||
|
(u_longlong_t)version, (u_longlong_t)newversion);
|
||||||
|
}
|
||||||
|
|
||||||
|
spa_upgrade(spa, newversion);
|
||||||
|
VERIFY3U(spa_version(spa), >, version);
|
||||||
|
VERIFY3U(spa_version(spa), ==, fnvlist_lookup_uint64(spa->spa_config,
|
||||||
|
zpool_prop_to_name(ZPOOL_PROP_VERSION)));
|
||||||
|
spa_close(spa, FTAG);
|
||||||
|
|
||||||
|
strfree(name);
|
||||||
|
mutex_exit(&ztest_vdev_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static vdev_t *
|
static vdev_t *
|
||||||
vdev_lookup_by_path(vdev_t *vd, const char *path)
|
vdev_lookup_by_path(vdev_t *vd, const char *path)
|
||||||
{
|
{
|
||||||
@ -2424,7 +2522,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
|
|||||||
/*
|
/*
|
||||||
* Make 1/4 of the devices be log devices.
|
* Make 1/4 of the devices be log devices.
|
||||||
*/
|
*/
|
||||||
nvroot = make_vdev_root(NULL, NULL,
|
nvroot = make_vdev_root(NULL, NULL, NULL,
|
||||||
ztest_opts.zo_vdev_size, 0,
|
ztest_opts.zo_vdev_size, 0,
|
||||||
ztest_random(4) == 0, ztest_opts.zo_raidz,
|
ztest_random(4) == 0, ztest_opts.zo_raidz,
|
||||||
zs->zs_mirrors, 1);
|
zs->zs_mirrors, 1);
|
||||||
@ -2503,7 +2601,7 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
|
|||||||
/*
|
/*
|
||||||
* Add a new device.
|
* Add a new device.
|
||||||
*/
|
*/
|
||||||
nvlist_t *nvroot = make_vdev_root(NULL, aux,
|
nvlist_t *nvroot = make_vdev_root(NULL, aux, NULL,
|
||||||
(ztest_opts.zo_vdev_size * 5) / 4, 0, 0, 0, 0, 1);
|
(ztest_opts.zo_vdev_size * 5) / 4, 0, 0, 0, 0, 1);
|
||||||
error = spa_vdev_add(spa, nvroot);
|
error = spa_vdev_add(spa, nvroot);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
@ -2776,7 +2874,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
|
|||||||
/*
|
/*
|
||||||
* Build the nvlist describing newpath.
|
* Build the nvlist describing newpath.
|
||||||
*/
|
*/
|
||||||
root = make_vdev_root(newpath, NULL, newvd == NULL ? newsize : 0,
|
root = make_vdev_root(newpath, NULL, NULL, newvd == NULL ? newsize : 0,
|
||||||
ashift, 0, 0, 0, 1);
|
ashift, 0, 0, 0, 1);
|
||||||
|
|
||||||
error = spa_vdev_attach(spa, oldguid, root, replacing);
|
error = spa_vdev_attach(spa, oldguid, root, replacing);
|
||||||
@ -5055,7 +5153,7 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
|
|||||||
if (error != 0)
|
if (error != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ztest_opts.zo_verbose >= 3) {
|
if (ztest_opts.zo_verbose >= 4) {
|
||||||
(void) printf("Changed guid old %llu -> %llu\n",
|
(void) printf("Changed guid old %llu -> %llu\n",
|
||||||
(u_longlong_t)orig, (u_longlong_t)spa_guid(spa));
|
(u_longlong_t)orig, (u_longlong_t)spa_guid(spa));
|
||||||
}
|
}
|
||||||
@ -5819,7 +5917,7 @@ ztest_init(ztest_shared_t *zs)
|
|||||||
ztest_shared->zs_vdev_next_leaf = 0;
|
ztest_shared->zs_vdev_next_leaf = 0;
|
||||||
zs->zs_splits = 0;
|
zs->zs_splits = 0;
|
||||||
zs->zs_mirrors = ztest_opts.zo_mirrors;
|
zs->zs_mirrors = ztest_opts.zo_mirrors;
|
||||||
nvroot = make_vdev_root(NULL, NULL, ztest_opts.zo_vdev_size, 0,
|
nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0,
|
||||||
0, ztest_opts.zo_raidz, zs->zs_mirrors, 1);
|
0, ztest_opts.zo_raidz, zs->zs_mirrors, 1);
|
||||||
props = make_random_props();
|
props = make_random_props();
|
||||||
for (i = 0; i < SPA_FEATURES; i++) {
|
for (i = 0; i < SPA_FEATURES; i++) {
|
||||||
|
@ -5742,6 +5742,14 @@ spa_sync_config_object(spa_t *spa, dmu_tx_t *tx)
|
|||||||
config = spa_config_generate(spa, spa->spa_root_vdev,
|
config = spa_config_generate(spa, spa->spa_root_vdev,
|
||||||
dmu_tx_get_txg(tx), B_FALSE);
|
dmu_tx_get_txg(tx), B_FALSE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're upgrading the spa version then make sure that
|
||||||
|
* the config object gets updated with the correct version.
|
||||||
|
*/
|
||||||
|
if (spa->spa_ubsync.ub_version < spa->spa_uberblock.ub_version)
|
||||||
|
fnvlist_add_uint64(config, ZPOOL_CONFIG_VERSION,
|
||||||
|
spa->spa_uberblock.ub_version);
|
||||||
|
|
||||||
spa_config_exit(spa, SCL_STATE, FTAG);
|
spa_config_exit(spa, SCL_STATE, FTAG);
|
||||||
|
|
||||||
if (spa->spa_config_syncing)
|
if (spa->spa_config_syncing)
|
||||||
|
Loading…
Reference in New Issue
Block a user