Skip import activity test in more zdb code paths

Since zdb opens the pools read-only, it cannot damage the pool in the
event the pool is already imported either on the same host or on
another one.

If the pool vdev structure is changing while zdb is importing the
pool, it may cause zdb to crash.  However this is unlikely, and in any
case it's a user space process and can simply be run again.

For this reason, zdb should disable the multihost activity test on
import that is normally run.

This commit fixes a few zdb code paths where that had been overlooked.
It also adds tests to ensure that several common use cases handle this
properly in the future.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Gu Zheng <guzheng2331314@163.com>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #7797 
Closes #7801
This commit is contained in:
Olaf Faaland 2018-08-20 10:05:23 -07:00 committed by Brian Behlendorf
parent edc05fdb34
commit 34fe773e30
4 changed files with 110 additions and 17 deletions

View File

@ -24,7 +24,7 @@
* Copyright (c) 2011, 2017 by Delphix. All rights reserved. * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com] * Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Nexenta Systems, Inc. * Copyright 2016 Nexenta Systems, Inc.
* Copyright (c) 2017 Lawrence Livermore National Security, LLC. * Copyright (c) 2017, 2018 Lawrence Livermore National Security, LLC.
* Copyright (c) 2015, 2017, Intel Corporation. * Copyright (c) 2015, 2017, Intel Corporation.
*/ */
@ -4558,6 +4558,22 @@ verify_device_removal_feature_counts(spa_t *spa)
return (ret); return (ret);
} }
static void
zdb_set_skip_mmp(char *target)
{
spa_t *spa;
/*
* Disable the activity check to allow examination of
* active pools.
*/
mutex_enter(&spa_namespace_lock);
if ((spa = spa_lookup(target)) != NULL) {
spa->spa_import_flags |= ZFS_IMPORT_SKIP_MMP;
}
mutex_exit(&spa_namespace_lock);
}
#define BOGUS_SUFFIX "_CHECKPOINTED_UNIVERSE" #define BOGUS_SUFFIX "_CHECKPOINTED_UNIVERSE"
/* /*
* Import the checkpointed state of the pool specified by the target * Import the checkpointed state of the pool specified by the target
@ -4592,6 +4608,7 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
} }
if (cfg == NULL) { if (cfg == NULL) {
zdb_set_skip_mmp(poolname);
error = spa_get_stats(poolname, &cfg, NULL, 0); error = spa_get_stats(poolname, &cfg, NULL, 0);
if (error != 0) { if (error != 0) {
fatal("Tried to read config of pool \"%s\" but " fatal("Tried to read config of pool \"%s\" but "
@ -4605,7 +4622,8 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
fnvlist_add_string(cfg, ZPOOL_CONFIG_POOL_NAME, bogus_name); fnvlist_add_string(cfg, ZPOOL_CONFIG_POOL_NAME, bogus_name);
error = spa_import(bogus_name, cfg, NULL, error = spa_import(bogus_name, cfg, NULL,
ZFS_IMPORT_MISSING_LOG | ZFS_IMPORT_CHECKPOINT); ZFS_IMPORT_MISSING_LOG | ZFS_IMPORT_CHECKPOINT |
ZFS_IMPORT_SKIP_MMP);
if (error != 0) { if (error != 0) {
fatal("Tried to import pool \"%s\" but spa_import() failed " fatal("Tried to import pool \"%s\" but spa_import() failed "
"with error %d\n", bogus_name, error); "with error %d\n", bogus_name, error);
@ -5739,15 +5757,15 @@ main(int argc, char **argv)
target, strerror(ENOMEM)); target, strerror(ENOMEM));
} }
/*
* Disable the activity check to allow examination of
* active pools.
*/
if (dump_opt['C'] > 1) { if (dump_opt['C'] > 1) {
(void) printf("\nConfiguration for import:\n"); (void) printf("\nConfiguration for import:\n");
dump_nvlist(cfg, 8); dump_nvlist(cfg, 8);
} }
/*
* Disable the activity check to allow examination of
* active pools.
*/
error = spa_import(target_pool, cfg, NULL, error = spa_import(target_pool, cfg, NULL,
flags | ZFS_IMPORT_SKIP_MMP); flags | ZFS_IMPORT_SKIP_MMP);
} }
@ -5769,16 +5787,7 @@ main(int argc, char **argv)
} }
} else if (target_is_spa || dump_opt['R']) { } else if (target_is_spa || dump_opt['R']) {
/* zdb_set_skip_mmp(target);
* Disable the activity check to allow examination of
* active pools.
*/
mutex_enter(&spa_namespace_lock);
if ((spa = spa_lookup(target)) != NULL) {
spa->spa_import_flags |= ZFS_IMPORT_SKIP_MMP;
}
mutex_exit(&spa_namespace_lock);
error = spa_open_rewind(target, &spa, FTAG, policy, error = spa_open_rewind(target, &spa, FTAG, policy,
NULL); NULL);
if (error) { if (error) {
@ -5801,6 +5810,7 @@ main(int argc, char **argv)
} }
} }
} else { } else {
zdb_set_skip_mmp(target);
error = open_objset(target, DMU_OST_ANY, FTAG, &os); error = open_objset(target, DMU_OST_ANY, FTAG, &os);
if (error == 0) if (error == 0)
spa = dmu_objset_spa(os); spa = dmu_objset_spa(os);

View File

@ -597,7 +597,8 @@ tags = ['functional', 'mmap']
[tests/functional/mmp] [tests/functional/mmp]
tests = ['mmp_on_thread', 'mmp_on_uberblocks', 'mmp_on_off', 'mmp_interval', tests = ['mmp_on_thread', 'mmp_on_uberblocks', 'mmp_on_off', 'mmp_interval',
'mmp_active_import', 'mmp_inactive_import', 'mmp_exported_import', 'mmp_active_import', 'mmp_inactive_import', 'mmp_exported_import',
'mmp_write_uberblocks', 'mmp_reset_interval', 'multihost_history'] 'mmp_write_uberblocks', 'mmp_reset_interval', 'multihost_history',
'mmp_on_zdb']
tags = ['functional', 'mmp'] tags = ['functional', 'mmp']
[tests/functional/mount] [tests/functional/mount]

View File

@ -10,6 +10,7 @@ dist_pkgdata_SCRIPTS = \
mmp_exported_import.ksh \ mmp_exported_import.ksh \
mmp_write_uberblocks.ksh \ mmp_write_uberblocks.ksh \
mmp_reset_interval.ksh \ mmp_reset_interval.ksh \
mmp_on_zdb.ksh \
setup.ksh \ setup.ksh \
cleanup.ksh cleanup.ksh

View File

@ -0,0 +1,81 @@
#!/bin/ksh
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright (c) 2018 Lawrence Livermore National Security, LLC.
# Copyright (c) 2018 by Nutanix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/mmp/mmp.cfg
. $STF_SUITE/tests/functional/mmp/mmp.kshlib
#
# Description:
# zdb will work while multihost is enabled.
#
# Strategy:
# 1. Create a pool
# 2. Enable multihost
# 3. Run zdb -d with pool and dataset arguments.
# 4. Create a checkpoint
# 5. Run zdb -kd with pool and dataset arguments.
# 6. Discard the checkpoint
# 7. Export the pool
# 8. Run zdb -ed with pool and dataset arguments.
#
function cleanup
{
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
for DISK in $DISKS; do
zpool labelclear -f $DEV_RDSKDIR/$DISK
done
log_must mmp_clear_hostid
}
log_assert "Verify zdb -d works while multihost is enabled"
log_onexit cleanup
verify_runnable "global"
verify_disk_count "$DISKS" 2
default_mirror_setup_noexit $DISKS
log_must mmp_set_hostid $HOSTID1
log_must zpool set multihost=on $TESTPOOL
log_must zfs snap $TESTPOOL/$TESTFS@snap
log_must zdb -d $TESTPOOL
log_must zdb -d $TESTPOOL/
log_must zdb -d $TESTPOOL/$TESTFS
log_must zdb -d $TESTPOOL/$TESTFS@snap
log_must zpool checkpoint $TESTPOOL
log_must zdb -kd $TESTPOOL
log_must zdb -kd $TESTPOOL/
log_must zdb -kd $TESTPOOL/$TESTFS
log_must zdb -kd $TESTPOOL/$TESTFS@snap
log_must zpool checkpoint -d $TESTPOOL
log_must zpool export $TESTPOOL
log_must zdb -ed $TESTPOOL
log_must zdb -ed $TESTPOOL/
log_must zdb -ed $TESTPOOL/$TESTFS
log_must zdb -ed $TESTPOOL/$TESTFS@snap
log_must zpool import $TESTPOOL
cleanup
log_pass "zdb -d works while multihost is enabled"