aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2020-02-26 15:45:04 +0000
committerAlexander Motin <mav@FreeBSD.org>2020-02-26 15:45:04 +0000
commit4b7f090f8d3d2f0eccef89c14f641319a19cf65c (patch)
tree370d3460ab9a5c69eda0cc9a414ffa54f0e92c32 /sys/cddl
parent06bd9afc5fcf4ac29557aa1a6aef819f2e0f1e7d (diff)
downloadsrc-4b7f090f8d3d2f0eccef89c14f641319a19cf65c.tar.gz
src-4b7f090f8d3d2f0eccef89c14f641319a19cf65c.zip
MFZoL: Fix txg_sync_thread hang in scan_exec_io()
When scn->scn_maxinflight_bytes has not been initialized it's possible to hang on the condition variable in scan_exec_io(). This issue was uncovered by ztest and is only possible when deduplication is enabled through the following call path. txg_sync_thread() spa_sync() ddt_sync_table() ddt_sync_entry() dsl_scan_ddt_entry() dsl_scan_scrub_cb() dsl_scan_enqueuei() scan_exec_io() cv_wait() Resolve the issue by always initializing scn_maxinflight_bytes to a reasonable minimum value. This value will be recalculated in dsl_scan_sync() to pick up changes to zfs_scan_vdev_limit and the addition/removal of vdevs. Reviewed-by: Tom Caputi <tcaputi@datto.com> Reviewed by: George Melikov <mail@gmelikov.ru> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #7098 zfsonlinux/zfs@f90a30ad1b32a971f62a540f8944e42f99b254ce MFC after: 1 week
Notes
Notes: svn path=/head/; revision=358336
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
index 316b09ad5db9..a3f3c51c5dca 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
@@ -125,6 +125,7 @@ static boolean_t scan_ds_queue_contains(dsl_scan_t *scn, uint64_t dsobj,
static void scan_ds_queue_insert(dsl_scan_t *scn, uint64_t dsobj, uint64_t txg);
static void scan_ds_queue_remove(dsl_scan_t *scn, uint64_t dsobj);
static void scan_ds_queue_sync(dsl_scan_t *scn, dmu_tx_t *tx);
+static uint64_t dsl_scan_count_leaves(vdev_t *vd);
extern int zfs_vdev_async_write_active_min_dirty_percent;
@@ -439,6 +440,14 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
scn->scn_async_destroying = spa_feature_is_active(dp->dp_spa,
SPA_FEATURE_ASYNC_DESTROY);
+ /*
+ * Calculate the max number of in-flight bytes for pool-wide
+ * scanning operations (minimum 1MB). Limits for the issuing
+ * phase are done per top-level vdev and are handled separately.
+ */
+ scn->scn_maxinflight_bytes = MAX(zfs_scan_vdev_limit *
+ dsl_scan_count_leaves(spa->spa_root_vdev), 1ULL << 20);
+
bcopy(&scn->scn_phys, &scn->scn_phys_cached, sizeof (scn->scn_phys));
avl_create(&scn->scn_queue, scan_ds_queue_compare, sizeof (scan_ds_t),
offsetof(scan_ds_t, sds_node));
@@ -2350,7 +2359,7 @@ dsl_scan_ddt_entry(dsl_scan_t *scn, enum zio_checksum checksum,
zbookmark_phys_t zb = { 0 };
int p;
- if (scn->scn_phys.scn_state != DSS_SCANNING)
+ if (!dsl_scan_is_running(scn))
return;
for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
@@ -3333,7 +3342,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
uint64_t nr_leaves = dsl_scan_count_leaves(spa->spa_root_vdev);
/*
- * Calculate the max number of in-flight bytes for pool-wide
+ * Recalculate the max number of in-flight bytes for pool-wide
* scanning operations (minimum 1MB). Limits for the issuing
* phase are done per top-level vdev and are handled separately.
*/
@@ -3653,6 +3662,8 @@ dsl_scan_scrub_done(zio_t *zio)
abd_free(zio->io_abd);
+ ASSERT3U(scn->scn_maxinflight_bytes, >, 0);
+
if (queue == NULL) {
mutex_enter(&spa->spa_scrub_lock);
ASSERT3U(spa->spa_scrub_inflight, >=, BP_GET_PSIZE(bp));