aboutsummaryrefslogtreecommitdiffstats
path: root/include/sys
diff options
context:
space:
mode:
authorOlaf Faaland <[email protected]>2019-03-12 10:37:06 -0700
committerBrian Behlendorf <[email protected]>2019-03-12 10:37:06 -0700
commit3d31aad83e6420d7a2f661ca077afdac13f50b77 (patch)
tree7eb5fc97bdc07188d2d415464ad9c39176bd3fd4 /include/sys
parentb1b94e9644ee6af27ce71d127618b7d5323561c6 (diff)
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 <[email protected]> Reviewed-by: Kash Pande <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: loli10K <[email protected]> Signed-off-by: Olaf Faaland <[email protected]> Closes #7953
Diffstat (limited to 'include/sys')
-rw-r--r--include/sys/mmp.h2
-rw-r--r--include/sys/spa_impl.h2
-rw-r--r--include/sys/vdev_impl.h1
3 files changed, 5 insertions, 0 deletions
diff --git a/include/sys/mmp.h b/include/sys/mmp.h
index c99c124e6..edb0d4347 100644
--- a/include/sys/mmp.h
+++ b/include/sys/mmp.h
@@ -44,6 +44,8 @@ typedef struct mmp_thread {
zio_t *mmp_zio_root; /* root of mmp write zios */
uint64_t mmp_kstat_id; /* unique id for next MMP write kstat */
int mmp_skip_error; /* reason for last skipped write */
+ vdev_t *mmp_last_leaf; /* last mmp write sent here */
+ uint64_t mmp_leaf_last_gen; /* last mmp write sent here */
} mmp_thread_t;
diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
index 404aaa9ee..c3aaad611 100644
--- a/include/sys/spa_impl.h
+++ b/include/sys/spa_impl.h
@@ -391,6 +391,8 @@ struct spa {
taskq_t *spa_prefetch_taskq; /* Taskq for prefetch threads */
uint64_t spa_multihost; /* multihost aware (mmp) */
mmp_thread_t spa_mmp; /* multihost mmp thread */
+ list_t spa_leaf_list; /* list of leaf vdevs */
+ uint64_t spa_leaf_list_gen; /* track leaf_list changes */
/*
* spa_refcount & spa_config_lock must be the last elements
diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h
index 8f8a8ccf6..c115a5e10 100644
--- a/include/sys/vdev_impl.h
+++ b/include/sys/vdev_impl.h
@@ -364,6 +364,7 @@ struct vdev {
hrtime_t vdev_mmp_pending; /* 0 if write finished */
uint64_t vdev_mmp_kstat_id; /* to find kstat entry */
uint64_t vdev_expansion_time; /* vdev's last expansion time */
+ list_node_t vdev_leaf_node; /* leaf vdev list */
/*
* For DTrace to work in userland (libzpool) context, these fields must