Add the ability to uninitialize
zpool initialize functions well for touching every free byte...once. But if we want to do it again, we're currently out of luck. So let's add zpool initialize -u to clear it. Co-authored-by: Rich Ercolani <rincebrain@gmail.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Rich Ercolani <rincebrain@gmail.com> Closes #12451 Closes #14873
This commit is contained in:
parent
e0d5007bcf
commit
e34e15ed6d
|
@ -398,7 +398,7 @@ get_usage(zpool_help_t idx)
|
||||||
case HELP_REOPEN:
|
case HELP_REOPEN:
|
||||||
return (gettext("\treopen [-n] <pool>\n"));
|
return (gettext("\treopen [-n] <pool>\n"));
|
||||||
case HELP_INITIALIZE:
|
case HELP_INITIALIZE:
|
||||||
return (gettext("\tinitialize [-c | -s] [-w] <pool> "
|
return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
|
||||||
"[<device> ...]\n"));
|
"[<device> ...]\n"));
|
||||||
case HELP_SCRUB:
|
case HELP_SCRUB:
|
||||||
return (gettext("\tscrub [-s | -p] [-w] <pool> ...\n"));
|
return (gettext("\tscrub [-s | -p] [-w] <pool> ...\n"));
|
||||||
|
@ -585,12 +585,13 @@ usage(boolean_t requested)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zpool initialize [-c | -s] [-w] <pool> [<vdev> ...]
|
* zpool initialize [-c | -s | -u] [-w] <pool> [<vdev> ...]
|
||||||
* Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
|
* Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
|
||||||
* if none specified.
|
* if none specified.
|
||||||
*
|
*
|
||||||
* -c Cancel. Ends active initializing.
|
* -c Cancel. Ends active initializing.
|
||||||
* -s Suspend. Initializing can then be restarted with no flags.
|
* -s Suspend. Initializing can then be restarted with no flags.
|
||||||
|
* -u Uninitialize. Clears initialization state.
|
||||||
* -w Wait. Blocks until initializing has completed.
|
* -w Wait. Blocks until initializing has completed.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
@ -606,12 +607,14 @@ zpool_do_initialize(int argc, char **argv)
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{"cancel", no_argument, NULL, 'c'},
|
{"cancel", no_argument, NULL, 'c'},
|
||||||
{"suspend", no_argument, NULL, 's'},
|
{"suspend", no_argument, NULL, 's'},
|
||||||
|
{"uninit", no_argument, NULL, 'u'},
|
||||||
{"wait", no_argument, NULL, 'w'},
|
{"wait", no_argument, NULL, 'w'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
|
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
|
||||||
while ((c = getopt_long(argc, argv, "csw", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "csuw", long_options,
|
||||||
|
NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (cmd_type != POOL_INITIALIZE_START &&
|
if (cmd_type != POOL_INITIALIZE_START &&
|
||||||
|
@ -631,6 +634,15 @@ zpool_do_initialize(int argc, char **argv)
|
||||||
}
|
}
|
||||||
cmd_type = POOL_INITIALIZE_SUSPEND;
|
cmd_type = POOL_INITIALIZE_SUSPEND;
|
||||||
break;
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (cmd_type != POOL_INITIALIZE_START &&
|
||||||
|
cmd_type != POOL_INITIALIZE_UNINIT) {
|
||||||
|
(void) fprintf(stderr, gettext("-u cannot be "
|
||||||
|
"combined with other options\n"));
|
||||||
|
usage(B_FALSE);
|
||||||
|
}
|
||||||
|
cmd_type = POOL_INITIALIZE_UNINIT;
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
wait = B_TRUE;
|
wait = B_TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -657,8 +669,8 @@ zpool_do_initialize(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait && (cmd_type != POOL_INITIALIZE_START)) {
|
if (wait && (cmd_type != POOL_INITIALIZE_START)) {
|
||||||
(void) fprintf(stderr, gettext("-w cannot be used with -c or "
|
(void) fprintf(stderr, gettext("-w cannot be used with -c, -s"
|
||||||
"-s\n"));
|
"or -u\n"));
|
||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1265,6 +1265,7 @@ typedef enum pool_initialize_func {
|
||||||
POOL_INITIALIZE_START,
|
POOL_INITIALIZE_START,
|
||||||
POOL_INITIALIZE_CANCEL,
|
POOL_INITIALIZE_CANCEL,
|
||||||
POOL_INITIALIZE_SUSPEND,
|
POOL_INITIALIZE_SUSPEND,
|
||||||
|
POOL_INITIALIZE_UNINIT,
|
||||||
POOL_INITIALIZE_FUNCS
|
POOL_INITIALIZE_FUNCS
|
||||||
} pool_initialize_func_t;
|
} pool_initialize_func_t;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void vdev_initialize(vdev_t *vd);
|
extern void vdev_initialize(vdev_t *vd);
|
||||||
|
extern void vdev_uninitialize(vdev_t *vd);
|
||||||
extern void vdev_initialize_stop(vdev_t *vd,
|
extern void vdev_initialize_stop(vdev_t *vd,
|
||||||
vdev_initializing_state_t tgt_state, list_t *vd_list);
|
vdev_initializing_state_t tgt_state, list_t *vd_list);
|
||||||
extern void vdev_initialize_stop_all(vdev_t *vd,
|
extern void vdev_initialize_stop_all(vdev_t *vd,
|
||||||
|
|
|
@ -5741,7 +5741,8 @@
|
||||||
<enumerator name='POOL_INITIALIZE_START' value='0'/>
|
<enumerator name='POOL_INITIALIZE_START' value='0'/>
|
||||||
<enumerator name='POOL_INITIALIZE_CANCEL' value='1'/>
|
<enumerator name='POOL_INITIALIZE_CANCEL' value='1'/>
|
||||||
<enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/>
|
<enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/>
|
||||||
<enumerator name='POOL_INITIALIZE_FUNCS' value='3'/>
|
<enumerator name='POOL_INITIALIZE_UNINIT' value='3'/>
|
||||||
|
<enumerator name='POOL_INITIALIZE_FUNCS' value='4'/>
|
||||||
</enum-decl>
|
</enum-decl>
|
||||||
<typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/>
|
<typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/>
|
||||||
<enum-decl name='pool_trim_func' id='54ed608a'>
|
<enum-decl name='pool_trim_func' id='54ed608a'>
|
||||||
|
|
|
@ -2387,8 +2387,8 @@ xlate_init_err(int err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Begin, suspend, or cancel the initialization (initializing of all free
|
* Begin, suspend, cancel, or uninit (clear) the initialization (initializing
|
||||||
* blocks) for the given vdevs in the given pool.
|
* of all free blocks) for the given vdevs in the given pool.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
|
zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
|
||||||
|
@ -2414,11 +2414,16 @@ zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
|
||||||
vdev_guids, &errlist);
|
vdev_guids, &errlist);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
if (errlist != NULL) {
|
if (errlist != NULL && nvlist_lookup_nvlist(errlist,
|
||||||
vd_errlist = fnvlist_lookup_nvlist(errlist,
|
ZPOOL_INITIALIZE_VDEVS, &vd_errlist) == 0) {
|
||||||
ZPOOL_INITIALIZE_VDEVS);
|
|
||||||
goto list_errors;
|
goto list_errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (err == EINVAL && cmd_type == POOL_INITIALIZE_UNINIT) {
|
||||||
|
zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
|
||||||
|
"uninitialize is not supported by kernel"));
|
||||||
|
}
|
||||||
|
|
||||||
(void) zpool_standard_error(zhp->zpool_hdl, err,
|
(void) zpool_standard_error(zhp->zpool_hdl, err,
|
||||||
dgettext(TEXT_DOMAIN, "operation failed"));
|
dgettext(TEXT_DOMAIN, "operation failed"));
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -1249,7 +1249,8 @@
|
||||||
<enumerator name='POOL_INITIALIZE_START' value='0'/>
|
<enumerator name='POOL_INITIALIZE_START' value='0'/>
|
||||||
<enumerator name='POOL_INITIALIZE_CANCEL' value='1'/>
|
<enumerator name='POOL_INITIALIZE_CANCEL' value='1'/>
|
||||||
<enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/>
|
<enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/>
|
||||||
<enumerator name='POOL_INITIALIZE_FUNCS' value='3'/>
|
<enumerator name='POOL_INITIALIZE_UNINIT' value='3'/>
|
||||||
|
<enumerator name='POOL_INITIALIZE_FUNCS' value='4'/>
|
||||||
</enum-decl>
|
</enum-decl>
|
||||||
<typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/>
|
<typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/>
|
||||||
<enum-decl name='pool_trim_func' id='54ed608a'>
|
<enum-decl name='pool_trim_func' id='54ed608a'>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm zpool
|
.Nm zpool
|
||||||
.Cm initialize
|
.Cm initialize
|
||||||
.Op Fl c Ns | Ns Fl s
|
.Op Fl c Ns | Ns Fl s | Ns Fl u
|
||||||
.Op Fl w
|
.Op Fl w
|
||||||
.Ar pool
|
.Ar pool
|
||||||
.Oo Ar device Oc Ns …
|
.Oo Ar device Oc Ns …
|
||||||
|
@ -60,6 +60,14 @@ initialized, the command will fail and no suspension will occur on any device.
|
||||||
Initializing can then be resumed by running
|
Initializing can then be resumed by running
|
||||||
.Nm zpool Cm initialize
|
.Nm zpool Cm initialize
|
||||||
with no flags on the relevant target devices.
|
with no flags on the relevant target devices.
|
||||||
|
.It Fl u , -uninit
|
||||||
|
Clears the initialization state on the specified devices, or all eligible
|
||||||
|
devices if none are specified.
|
||||||
|
If the devices are being actively initialized the command will fail.
|
||||||
|
After being cleared
|
||||||
|
.Nm zpool Cm initialize
|
||||||
|
with no flags can be used to re-initialize all unallocoated regions on
|
||||||
|
the relevant target devices.
|
||||||
.It Fl w , -wait
|
.It Fl w , -wait
|
||||||
Wait until the devices have finished initializing before returning.
|
Wait until the devices have finished initializing before returning.
|
||||||
.El
|
.El
|
||||||
|
|
|
@ -7421,6 +7421,10 @@ spa_vdev_initialize_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type,
|
||||||
vd->vdev_initialize_state != VDEV_INITIALIZE_ACTIVE) {
|
vd->vdev_initialize_state != VDEV_INITIALIZE_ACTIVE) {
|
||||||
mutex_exit(&vd->vdev_initialize_lock);
|
mutex_exit(&vd->vdev_initialize_lock);
|
||||||
return (SET_ERROR(ESRCH));
|
return (SET_ERROR(ESRCH));
|
||||||
|
} else if (cmd_type == POOL_INITIALIZE_UNINIT &&
|
||||||
|
vd->vdev_initialize_thread != NULL) {
|
||||||
|
mutex_exit(&vd->vdev_initialize_lock);
|
||||||
|
return (SET_ERROR(EBUSY));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd_type) {
|
switch (cmd_type) {
|
||||||
|
@ -7433,6 +7437,9 @@ spa_vdev_initialize_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type,
|
||||||
case POOL_INITIALIZE_SUSPEND:
|
case POOL_INITIALIZE_SUSPEND:
|
||||||
vdev_initialize_stop(vd, VDEV_INITIALIZE_SUSPENDED, vd_list);
|
vdev_initialize_stop(vd, VDEV_INITIALIZE_SUSPENDED, vd_list);
|
||||||
break;
|
break;
|
||||||
|
case POOL_INITIALIZE_UNINIT:
|
||||||
|
vdev_uninitialize(vd);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
panic("invalid cmd_type %llu", (unsigned long long)cmd_type);
|
panic("invalid cmd_type %llu", (unsigned long long)cmd_type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,39 @@ vdev_initialize_zap_update_sync(void *arg, dmu_tx_t *tx)
|
||||||
&initialize_state, tx));
|
&initialize_state, tx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vdev_initialize_zap_remove_sync(void *arg, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
uint64_t guid = *(uint64_t *)arg;
|
||||||
|
|
||||||
|
kmem_free(arg, sizeof (uint64_t));
|
||||||
|
|
||||||
|
vdev_t *vd = spa_lookup_by_guid(tx->tx_pool->dp_spa, guid, B_FALSE);
|
||||||
|
if (vd == NULL || vd->vdev_top->vdev_removing || !vdev_is_concrete(vd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ASSERT3S(vd->vdev_initialize_state, ==, VDEV_INITIALIZE_NONE);
|
||||||
|
ASSERT3U(vd->vdev_leaf_zap, !=, 0);
|
||||||
|
|
||||||
|
vd->vdev_initialize_last_offset = 0;
|
||||||
|
vd->vdev_initialize_action_time = 0;
|
||||||
|
|
||||||
|
objset_t *mos = vd->vdev_spa->spa_meta_objset;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = zap_remove(mos, vd->vdev_leaf_zap,
|
||||||
|
VDEV_LEAF_ZAP_INITIALIZE_LAST_OFFSET, tx);
|
||||||
|
VERIFY(error == 0 || error == ENOENT);
|
||||||
|
|
||||||
|
error = zap_remove(mos, vd->vdev_leaf_zap,
|
||||||
|
VDEV_LEAF_ZAP_INITIALIZE_STATE, tx);
|
||||||
|
VERIFY(error == 0 || error == ENOENT);
|
||||||
|
|
||||||
|
error = zap_remove(mos, vd->vdev_leaf_zap,
|
||||||
|
VDEV_LEAF_ZAP_INITIALIZE_ACTION_TIME, tx);
|
||||||
|
VERIFY(error == 0 || error == ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
|
vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
|
||||||
{
|
{
|
||||||
|
@ -123,8 +156,14 @@ vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
|
||||||
|
|
||||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||||
dsl_sync_task_nowait(spa_get_dsl(spa), vdev_initialize_zap_update_sync,
|
|
||||||
guid, tx);
|
if (new_state != VDEV_INITIALIZE_NONE) {
|
||||||
|
dsl_sync_task_nowait(spa_get_dsl(spa),
|
||||||
|
vdev_initialize_zap_update_sync, guid, tx);
|
||||||
|
} else {
|
||||||
|
dsl_sync_task_nowait(spa_get_dsl(spa),
|
||||||
|
vdev_initialize_zap_remove_sync, guid, tx);
|
||||||
|
}
|
||||||
|
|
||||||
switch (new_state) {
|
switch (new_state) {
|
||||||
case VDEV_INITIALIZE_ACTIVE:
|
case VDEV_INITIALIZE_ACTIVE:
|
||||||
|
@ -145,6 +184,10 @@ vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
|
||||||
spa_history_log_internal(spa, "initialize", tx,
|
spa_history_log_internal(spa, "initialize", tx,
|
||||||
"vdev=%s complete", vd->vdev_path);
|
"vdev=%s complete", vd->vdev_path);
|
||||||
break;
|
break;
|
||||||
|
case VDEV_INITIALIZE_NONE:
|
||||||
|
spa_history_log_internal(spa, "uninitialize", tx,
|
||||||
|
"vdev=%s", vd->vdev_path);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
panic("invalid state %llu", (unsigned long long)new_state);
|
panic("invalid state %llu", (unsigned long long)new_state);
|
||||||
}
|
}
|
||||||
|
@ -594,6 +637,24 @@ vdev_initialize(vdev_t *vd)
|
||||||
vdev_initialize_thread, vd, 0, &p0, TS_RUN, maxclsyspri);
|
vdev_initialize_thread, vd, 0, &p0, TS_RUN, maxclsyspri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Uninitializes a device. Caller must hold vdev_initialize_lock.
|
||||||
|
* Device must be a leaf and not already be initializing.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vdev_uninitialize(vdev_t *vd)
|
||||||
|
{
|
||||||
|
ASSERT(MUTEX_HELD(&vd->vdev_initialize_lock));
|
||||||
|
ASSERT(vd->vdev_ops->vdev_op_leaf);
|
||||||
|
ASSERT(vdev_is_concrete(vd));
|
||||||
|
ASSERT3P(vd->vdev_initialize_thread, ==, NULL);
|
||||||
|
ASSERT(!vd->vdev_detached);
|
||||||
|
ASSERT(!vd->vdev_initialize_exit_wanted);
|
||||||
|
ASSERT(!vd->vdev_top->vdev_removing);
|
||||||
|
|
||||||
|
vdev_initialize_change_state(vd, VDEV_INITIALIZE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for the initialize thread to be terminated (cancelled or stopped).
|
* Wait for the initialize thread to be terminated (cancelled or stopped).
|
||||||
*/
|
*/
|
||||||
|
@ -750,6 +811,7 @@ vdev_initialize_restart(vdev_t *vd)
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(vdev_initialize);
|
EXPORT_SYMBOL(vdev_initialize);
|
||||||
|
EXPORT_SYMBOL(vdev_uninitialize);
|
||||||
EXPORT_SYMBOL(vdev_initialize_stop);
|
EXPORT_SYMBOL(vdev_initialize_stop);
|
||||||
EXPORT_SYMBOL(vdev_initialize_stop_all);
|
EXPORT_SYMBOL(vdev_initialize_stop_all);
|
||||||
EXPORT_SYMBOL(vdev_initialize_stop_wait);
|
EXPORT_SYMBOL(vdev_initialize_stop_wait);
|
||||||
|
|
|
@ -4070,7 +4070,8 @@ zfs_ioc_pool_initialize(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
|
||||||
|
|
||||||
if (!(cmd_type == POOL_INITIALIZE_CANCEL ||
|
if (!(cmd_type == POOL_INITIALIZE_CANCEL ||
|
||||||
cmd_type == POOL_INITIALIZE_START ||
|
cmd_type == POOL_INITIALIZE_START ||
|
||||||
cmd_type == POOL_INITIALIZE_SUSPEND)) {
|
cmd_type == POOL_INITIALIZE_SUSPEND ||
|
||||||
|
cmd_type == POOL_INITIALIZE_UNINIT)) {
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -446,6 +446,7 @@ tests = ['zpool_initialize_attach_detach_add_remove',
|
||||||
'zpool_initialize_start_and_cancel_neg',
|
'zpool_initialize_start_and_cancel_neg',
|
||||||
'zpool_initialize_start_and_cancel_pos',
|
'zpool_initialize_start_and_cancel_pos',
|
||||||
'zpool_initialize_suspend_resume',
|
'zpool_initialize_suspend_resume',
|
||||||
|
'zpool_initialize_uninit',
|
||||||
'zpool_initialize_unsupported_vdevs',
|
'zpool_initialize_unsupported_vdevs',
|
||||||
'zpool_initialize_verify_checksums',
|
'zpool_initialize_verify_checksums',
|
||||||
'zpool_initialize_verify_initialized']
|
'zpool_initialize_verify_initialized']
|
||||||
|
|
|
@ -1102,6 +1102,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||||
functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh \
|
functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh \
|
||||||
functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh \
|
functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh \
|
||||||
functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh \
|
functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh \
|
||||||
|
functional/cli_root/zpool_initialize/zpool_initialize_uninit.ksh \
|
||||||
functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh \
|
functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh \
|
||||||
functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh \
|
functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh \
|
||||||
functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh \
|
functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh \
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||||
|
# 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) 2016 by Delphix. All rights reserved.
|
||||||
|
# Copyright (C) 2023 Lawrence Livermore National Security, LLC.
|
||||||
|
#
|
||||||
|
. $STF_SUITE/include/libtest.shlib
|
||||||
|
. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
|
||||||
|
|
||||||
|
#
|
||||||
|
# DESCRIPTION:
|
||||||
|
# Starting, stopping, uninitializing, and restart an initialize works.
|
||||||
|
#
|
||||||
|
# STRATEGY:
|
||||||
|
# 1. Create a one-disk pool.
|
||||||
|
# 2. Verify uninitialize succeeds for uninitialized pool.
|
||||||
|
# 3. Verify pool wide cancel|suspend + uninit
|
||||||
|
# a. Start initializing and verify that initializing is active.
|
||||||
|
# b. Verify uninitialize fails when actively initializing.
|
||||||
|
# c. Cancel or suspend initializing and verify that initializing is not active.
|
||||||
|
# d. Verify uninitialize succeeds after being cancelled.
|
||||||
|
# 4. Verify per-disk cancel|suspend + uninit
|
||||||
|
#
|
||||||
|
|
||||||
|
DISK1="$(echo $DISKS | cut -d' ' -f1)"
|
||||||
|
DISK2="$(echo $DISKS | cut -d' ' -f2)"
|
||||||
|
DISK3="$(echo $DISKS | cut -d' ' -f3)"
|
||||||
|
|
||||||
|
function status_check # pool disk1-state disk2-state disk3-state
|
||||||
|
{
|
||||||
|
typeset pool="$1"
|
||||||
|
typeset disk1_state="$2"
|
||||||
|
typeset disk2_state="$3"
|
||||||
|
typeset disk3_state="$4"
|
||||||
|
|
||||||
|
state=$(zpool status -i "$pool" | grep "$DISK1" | grep "$disk1_state")
|
||||||
|
if [[ -z "$state" ]]; then
|
||||||
|
log_fail "DISK1 state; expected='$disk1_state' got '$state'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
state=$(zpool status -i "$pool" | grep "$DISK2" | grep "$disk2_state")
|
||||||
|
if [[ -z "$state" ]]; then
|
||||||
|
log_fail "DISK2 state; expected='$disk2_state' got '$state'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
state=$(zpool status -i "$pool" | grep "$DISK3" | grep "$disk3_state")
|
||||||
|
if [[ -z "$state" ]]; then
|
||||||
|
log_fail "DISK3 state; expected='$disk3_state' got '$state'"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function status_check_all # pool disk-state
|
||||||
|
{
|
||||||
|
typeset pool="$1"
|
||||||
|
typeset disk_state="$2"
|
||||||
|
|
||||||
|
status_check "$pool" "$disk_state" "$disk_state" "$disk_state"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. Create a one-disk pool.
|
||||||
|
log_must zpool create -f $TESTPOOL $DISK1 $DISK2 $DISK3
|
||||||
|
status_check_all $TESTPOOL "uninitialized"
|
||||||
|
|
||||||
|
# 2. Verify uninitialize succeeds for uninitialized pool.
|
||||||
|
log_must zpool initialize -u $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "uninitialized"
|
||||||
|
|
||||||
|
# 3. Verify pool wide cancel + uninit
|
||||||
|
log_must zpool initialize $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_mustnot zpool initialize -u $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -c $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "uninitialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -u $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "uninitialized"
|
||||||
|
|
||||||
|
# 3. Verify pool wide suspend + uninit
|
||||||
|
log_must zpool initialize $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_mustnot zpool initialize -u $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -s $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "suspended"
|
||||||
|
|
||||||
|
log_must zpool initialize -u $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "uninitialized"
|
||||||
|
|
||||||
|
# 4. Verify per-disk cancel|suspend + uninit
|
||||||
|
log_must zpool initialize $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -c $TESTPOOL $DISK1
|
||||||
|
log_must zpool initialize -s $TESTPOOL $DISK2
|
||||||
|
log_mustnot zpool initialize -u $TESTPOOL $DISK3
|
||||||
|
status_check $TESTPOOL "uninitialized" "suspended" "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -u $TESTPOOL $DISK1
|
||||||
|
status_check $TESTPOOL "uninitialized" "suspended" "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -u $TESTPOOL $DISK2
|
||||||
|
status_check $TESTPOOL "uninitialized" "uninitialized" "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize $TESTPOOL $DISK1
|
||||||
|
status_check $TESTPOOL "[[:digit:]]* initialized" "uninitialized" "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize $TESTPOOL $DISK2
|
||||||
|
status_check_all $TESTPOOL "[[:digit:]]* initialized"
|
||||||
|
|
||||||
|
log_must zpool initialize -s $TESTPOOL
|
||||||
|
status_check_all $TESTPOOL "suspended"
|
||||||
|
|
||||||
|
log_must zpool initialize -u $TESTPOOL $DISK1 $DISK2 $DISK3
|
||||||
|
status_check_all $TESTPOOL "uninitialized"
|
||||||
|
|
||||||
|
log_pass "Initialize start + cancel/suspend + uninit + start works"
|
Loading…
Reference in New Issue