mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
MMP writes rotate over leaves
Instead of choosing a leaf vdev quasi-randomly, by starting at the root
vdev and randomly choosing children, rotate over leaves to issue MMP
writes. This fixes an issue in a pool whose top-level vdevs have
different numbers of leaves.
The issue is that the frequency at which individual leaves are chosen
for MMP writes is based not on the total number of leaves but based on
how many siblings the leaves have.
For example, in a pool like this:
root-vdev
+------+---------------+
vdev1 vdev2
| |
| +------+-----+-----+----+
disk1 disk2 disk3 disk4 disk5 disk6
vdev1 and vdev2 will each be chosen 50% of the time. Every time vdev1
is chosen, disk1 will be chosen. However, every time vdev2 is chosen,
disk2 is chosen 20% of the time. As a result, disk1 will be sent 5x as
many MMP writes as disk2.
This may create wear issues in the case of SSDs. It also reduces the
effectiveness of MMP as it depends on the writes being evenly
distributed for the case where some devices fail or are partitioned.
The new code maintains a list of leaf vdevs in the pool. MMP records
the last leaf used for an MMP write in mmp->mmp_last_leaf. To choose
the next leaf, MMP starts at mmp->mmp_last_leaf and traverses the list,
continuing from the head if the tail is reached. It stops when a
suitable leaf is found or all leaves have been examined.
Added a test to verify MMP write distribution is even.
Reviewed-by: Tom Caputi <tcaputi@datto.com>
Reviewed-by: Kash Pande <kash@tripleback.net>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #7953
This commit is contained in:
committed by
Brian Behlendorf
parent
b1b94e9644
commit
3d31aad83e
@@ -640,7 +640,7 @@ tags = ['functional', 'mmap']
|
||||
tests = ['mmp_on_thread', 'mmp_on_uberblocks', 'mmp_on_off', 'mmp_interval',
|
||||
'mmp_active_import', 'mmp_inactive_import', 'mmp_exported_import',
|
||||
'mmp_write_uberblocks', 'mmp_reset_interval', 'multihost_history',
|
||||
'mmp_on_zdb']
|
||||
'mmp_on_zdb', 'mmp_write_distribution']
|
||||
tags = ['functional', 'mmp']
|
||||
|
||||
[tests/functional/mount]
|
||||
|
||||
@@ -11,6 +11,7 @@ dist_pkgdata_SCRIPTS = \
|
||||
mmp_write_uberblocks.ksh \
|
||||
mmp_reset_interval.ksh \
|
||||
mmp_on_zdb.ksh \
|
||||
mmp_write_distribution.ksh \
|
||||
setup.ksh \
|
||||
cleanup.ksh
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
# DESCRIPTION:
|
||||
# Verify MMP writes are distributed evenly among leaves
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create an asymmetric mirrored pool
|
||||
# 2. Enable multihost and multihost_history
|
||||
# 3. Delay for MMP writes to occur
|
||||
# 4. Verify the MMP writes are distributed evenly across leaf vdevs
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/mmp/mmp.cfg
|
||||
. $STF_SUITE/tests/functional/mmp/mmp.kshlib
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must zpool destroy $MMP_POOL
|
||||
log_must rm $MMP_DIR/file.{0,1,2,3,4,5,6,7}
|
||||
log_must rm $MMP_HISTORY_TMP
|
||||
log_must rmdir $MMP_DIR
|
||||
log_must mmp_clear_hostid
|
||||
}
|
||||
|
||||
log_assert "mmp writes are evenly distributed across leaf vdevs"
|
||||
log_onexit cleanup
|
||||
|
||||
MMP_HISTORY_TMP=$MMP_DIR/history
|
||||
MMP_HISTORY=/proc/spl/kstat/zfs/$MMP_POOL/multihost
|
||||
|
||||
# Step 1
|
||||
log_must mkdir -p $MMP_DIR
|
||||
log_must truncate -s 128M $MMP_DIR/file.{0,1,2,3,4,5,6,7}
|
||||
log_must zpool create -f $MMP_POOL mirror $MMP_DIR/file.{0,1} mirror $MMP_DIR/file.{2,3,4,5,6,7}
|
||||
|
||||
# Step 2
|
||||
log_must mmp_set_hostid $HOSTID1
|
||||
log_must zpool set multihost=on $MMP_POOL
|
||||
set_tunable64 zfs_multihost_history 0
|
||||
set_tunable64 zfs_multihost_history 40
|
||||
|
||||
# Step 3
|
||||
# default settings, every leaf written once/second
|
||||
sleep 4
|
||||
|
||||
# Step 4
|
||||
typeset -i min_writes=999
|
||||
typeset -i max_writes=0
|
||||
typeset -i write_count
|
||||
# copy to get as close to a consistent view as possible
|
||||
cat $MMP_HISTORY > $MMP_HISTORY_TMP
|
||||
for x in $(seq 0 7); do
|
||||
write_count=$(grep -c file.${x} $MMP_HISTORY_TMP)
|
||||
if [ $write_count -lt $min_writes ]; then
|
||||
min_writes=$write_count
|
||||
fi
|
||||
if [ $write_count -gt $max_writes ]; then
|
||||
max_writes=$write_count
|
||||
fi
|
||||
done
|
||||
log_note "mmp min_writes $min_writes max_writes $max_writes"
|
||||
|
||||
if [ $min_writes -lt 1 ]; then
|
||||
log_fail "mmp writes were not counted correctly"
|
||||
fi
|
||||
|
||||
if [ $((max_writes - min_writes)) -gt 1 ]; then
|
||||
log_fail "mmp writes were not evenly distributed across leaf vdevs"
|
||||
fi
|
||||
|
||||
log_pass "mmp writes were evenly distributed across leaf vdevs"
|
||||
Reference in New Issue
Block a user