aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorAlexander Motin <[email protected]>2022-07-20 20:02:36 -0400
committerGitHub <[email protected]>2022-07-20 17:02:36 -0700
commit33dba8c79224ce33dc661d545ab1d17fc3d84a0c (patch)
tree2c4d92eabd6d04d4544c066ce62beaaf3f1e785e /module/zfs
parent97fd1ea42a59b85ca29c91056ceef56c12cfae0b (diff)
Fix scrub resume from newly created hole
It may happen that scan bookmark points to a block that was turned into a part of a big hole. In such case dsl_scan_visitbp() may skip it and dsl_scan_check_resume() will not be called for it. As result new scan suspend won't be possible until the end of the object, that may take hours if the object is a multi-terabyte ZVOL on a slow HDD pool, stretching TXG to all that time, creating all sorts of problems. This patch changes the resume condition to any greater or equal block, so even if we miss the bookmarked block, the next one we find will delete the bookmark, allowing new suspend. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Sponsored-By: iXsystems, Inc. Closes #13643
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dsl_scan.c10
-rw-r--r--module/zfs/zio.c18
2 files changed, 21 insertions, 7 deletions
diff --git a/module/zfs/dsl_scan.c b/module/zfs/dsl_scan.c
index 529d3da59..2b76bed1b 100644
--- a/module/zfs/dsl_scan.c
+++ b/module/zfs/dsl_scan.c
@@ -1802,13 +1802,11 @@ dsl_scan_check_resume(dsl_scan_t *scn, const dnode_phys_t *dnp,
/*
* If we found the block we're trying to resume from, or
- * we went past it to a different object, zero it out to
- * indicate that it's OK to start checking for suspending
- * again.
+ * we went past it, zero it out to indicate that it's OK
+ * to start checking for suspending again.
*/
- if (memcmp(zb, &scn->scn_phys.scn_bookmark,
- sizeof (*zb)) == 0 ||
- zb->zb_object > scn->scn_phys.scn_bookmark.zb_object) {
+ if (zbookmark_subtree_tbd(dnp, zb,
+ &scn->scn_phys.scn_bookmark)) {
dprintf("resuming at %llx/%llx/%llx/%llx\n",
(longlong_t)zb->zb_objset,
(longlong_t)zb->zb_object,
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 6018ce6ca..3d1ac36d9 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -4997,7 +4997,7 @@ zbookmark_subtree_completed(const dnode_phys_t *dnp,
{
zbookmark_phys_t mod_zb = *subtree_root;
mod_zb.zb_blkid++;
- ASSERT(last_block->zb_level == 0);
+ ASSERT0(last_block->zb_level);
/* The objset_phys_t isn't before anything. */
if (dnp == NULL)
@@ -5023,6 +5023,22 @@ zbookmark_subtree_completed(const dnode_phys_t *dnp,
last_block) <= 0);
}
+/*
+ * This function is similar to zbookmark_subtree_completed(), but returns true
+ * if subtree_root is equal or ahead of last_block, i.e. still to be done.
+ */
+boolean_t
+zbookmark_subtree_tbd(const dnode_phys_t *dnp,
+ const zbookmark_phys_t *subtree_root, const zbookmark_phys_t *last_block)
+{
+ ASSERT0(last_block->zb_level);
+ if (dnp == NULL)
+ return (B_FALSE);
+ return (zbookmark_compare(dnp->dn_datablkszsec, dnp->dn_indblkshift,
+ 1ULL << (DNODE_BLOCK_SHIFT - SPA_MINBLOCKSHIFT), 0, subtree_root,
+ last_block) >= 0);
+}
+
EXPORT_SYMBOL(zio_type_name);
EXPORT_SYMBOL(zio_buf_alloc);
EXPORT_SYMBOL(zio_data_buf_alloc);