Skip to content

Commit 504bfc8

Browse files
behlendorftonyhutter
authored andcommitted
Fix multihost stale cache file import
When the multihost property is enabled it should be impossible to import an active pool even using the force (-f) option. This patch prevents a forced import from succeeding when importing with a stale cache file. The root cause of the problem is that the kernel modules trusted the hostid provided in configuration. This is always correct when the configuration is generated by scanning for the pool. However, when using an existing cache file the hostid could be stale which would result in the activity check being skipped. Resolve the issue by always using the hostid read from the label configuration where the best uberblock was found. Reviewed-by: Olaf Faaland <[email protected]> Reviewed-by: Tony Hutter <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #6933 Closes #6971
1 parent 53a8cbd commit 504bfc8

File tree

4 files changed

+26
-9
lines changed

4 files changed

+26
-9
lines changed

module/zfs/spa.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,7 +2341,8 @@ vdev_count_verify_zaps(vdev_t *vd)
23412341
* Determine whether the activity check is required.
23422342
*/
23432343
static boolean_t
2344-
spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *config)
2344+
spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *label,
2345+
nvlist_t *config)
23452346
{
23462347
uint64_t state = 0;
23472348
uint64_t hostid = 0;
@@ -2358,7 +2359,6 @@ spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *config)
23582359
}
23592360

23602361
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state);
2361-
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
23622362

23632363
/*
23642364
* Disable the MMP activity check - This is used by zdb which
@@ -2384,8 +2384,12 @@ spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *config)
23842384

23852385
/*
23862386
* Allow the activity check to be skipped when importing the pool
2387-
* on the same host which last imported it.
2387+
* on the same host which last imported it. Since the hostid from
2388+
* configuration may be stale use the one read from the label.
23882389
*/
2390+
if (nvlist_exists(label, ZPOOL_CONFIG_HOSTID))
2391+
hostid = fnvlist_lookup_uint64(label, ZPOOL_CONFIG_HOSTID);
2392+
23892393
if (hostid == spa_get_hostid())
23902394
return (B_FALSE);
23912395

@@ -2651,7 +2655,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
26512655
* pool is truly inactive and can be safely imported. Prevent
26522656
* hosts which don't have a hostid set from importing the pool.
26532657
*/
2654-
activity_check = spa_activity_check_required(spa, ub, config);
2658+
activity_check = spa_activity_check_required(spa, ub, label, config);
26552659
if (activity_check) {
26562660
if (ub->ub_mmp_magic == MMP_MAGIC && ub->ub_mmp_delay &&
26572661
spa_get_hostid() == 0) {

tests/zfs-tests/tests/functional/mmp/mmp.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export TXG_TIMEOUT_DEFAULT=5
3030

3131
export MMP_POOL=mmppool
3232
export MMP_DIR=$TEST_BASE_DIR/mmp
33+
export MMP_CACHE=$MMP_DIR/zpool.cache
34+
export MMP_ZTEST_LOG=$MMP_DIR/ztest.log
3335
export MMP_HISTORY=100
3436
export MMP_HISTORY_OFF=0
3537

tests/zfs-tests/tests/functional/mmp/mmp.kshlib

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,24 @@ function mmp_pool_create # pool dir
9797
{
9898
typeset pool=${1:-$MMP_POOL}
9999
typeset dir=${2:-$MMP_DIR}
100-
typeset opts="-T120 -M -k0 -f $dir -E -p $pool"
100+
typeset opts="-VVVVV -T120 -M -k0 -f $dir -E -p $pool"
101101

102102
log_must mkdir -p $dir
103+
log_must rm -f $dir/*
103104
log_must truncate -s $MINVDEVSIZE $dir/vdev1 $dir/vdev2
104105

105106
log_must mmp_clear_hostid
106107
log_must mmp_set_hostid $HOSTID1
107-
log_must zpool create -f $pool mirror $dir/vdev1 $dir/vdev2
108+
log_must zpool create -f -o cachefile=$MMP_CACHE $pool \
109+
mirror $dir/vdev1 $dir/vdev2
108110
log_must zpool set multihost=on $pool
111+
log_must mv $MMP_CACHE ${MMP_CACHE}.stale
109112
log_must zpool export $pool
110113
log_must mmp_clear_hostid
111114
log_must mmp_set_hostid $HOSTID2
112115

113116
log_note "Starting ztest in the background as hostid $HOSTID1"
114-
log_must eval "ZFS_HOSTID=$HOSTID1 ztest $opts >/dev/null 2>&1 &"
117+
log_must eval "ZFS_HOSTID=$HOSTID1 ztest $opts >$MMP_ZTEST_LOG 2>&1 &"
115118

116119
while ! is_pool_imported "$pool" "-d $dir"; do
117120
log_must pgrep ztest
@@ -134,7 +137,7 @@ function mmp_pool_destroy # pool dir
134137
destroy_pool $pool
135138
fi
136139

137-
rm -Rf $dir
140+
log_must rm -f $dir/*
138141
mmp_clear_hostid
139142
}
140143

tests/zfs-tests/tests/functional/mmp/mmp_active_import.ksh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ verify_runnable "both"
4141

4242
function cleanup
4343
{
44-
mmp_pool_destroy $MMP_DIR $MMP_POOL
44+
mmp_pool_destroy $MMP_POOL $MMP_DIR
4545
log_must set_tunable64 zfs_multihost_interval $MMP_INTERVAL_DEFAULT
4646
log_must mmp_clear_hostid
4747
}
@@ -60,11 +60,19 @@ log_must is_pool_imported $MMP_POOL "-d $MMP_DIR"
6060

6161
# 3. Verify 'zpool import [-f] $MMP_POOL' cannot import the pool.
6262
MMP_IMPORTED_MSG="Cannot import '$MMP_POOL': pool is imported"
63+
6364
log_must try_pool_import $MMP_POOL "-d $MMP_DIR" "$MMP_IMPORTED_MSG"
6465
for i in {1..10}; do
6566
log_must try_pool_import $MMP_POOL "-f -d $MMP_DIR" "$MMP_IMPORTED_MSG"
6667
done
6768

69+
log_must try_pool_import $MMP_POOL "-c ${MMP_CACHE}.stale" "$MMP_IMPORTED_MSG"
70+
71+
for i in {1..10}; do
72+
log_must try_pool_import $MMP_POOL "-f -c ${MMP_CACHE}.stale" \
73+
"$MMP_IMPORTED_MSG"
74+
done
75+
6876
# 4. Kill ztest to make pool eligible for import. Poll with 'zpool status'.
6977
ZTESTPID=$(pgrep ztest)
7078
if [ -n "$ZTESTPID" ]; then

0 commit comments

Comments
 (0)