summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2015-12-11 11:09:41 -0800
committerBrian Behlendorf <[email protected]>2015-12-15 16:12:31 -0800
commiteba9e745dcfce252fc6c451cdf07c55bf975f1f6 (patch)
tree4b625a4111eaf9c5d971649e3cf08bf1cfeed2e2
parent1cdb86cba2750f6da468e021a5ae2ba9a24530df (diff)
Handle damaged blk_birth in dsl_deadlist_insert()
If a bit were cleared in `bp->blk_birth` such that the txg birth was now lower than any other txg_birth in the deadlist, then there will be no entry before this in the tree. This should be impossible but regardless error handling code has been added for this case. By default this is left as a fatal case and the blk_birth is logged. However, setting `zfs_recover=1` will cause the bp to be placed at the start of the deadlist even though it contains an invalid blk_birth. Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: Chunwei Chen <[email protected]> Closes #4086 Closes #4089
-rw-r--r--module/zfs/dsl_deadlist.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/module/zfs/dsl_deadlist.c b/module/zfs/dsl_deadlist.c
index 8da77ebd7..fa83a10a5 100644
--- a/module/zfs/dsl_deadlist.c
+++ b/module/zfs/dsl_deadlist.c
@@ -239,6 +239,14 @@ dsl_deadlist_insert(dsl_deadlist_t *dl, const blkptr_t *bp, dmu_tx_t *tx)
dle = avl_nearest(&dl->dl_tree, where, AVL_BEFORE);
else
dle = AVL_PREV(&dl->dl_tree, dle);
+
+ if (dle == NULL) {
+ zfs_panic_recover("blkptr at %p has invalid BLK_BIRTH %llu",
+ bp, (longlong_t)bp->blk_birth);
+ dle = avl_first(&dl->dl_tree);
+ }
+
+ ASSERT3P(dle, !=, NULL);
dle_enqueue(dl, dle, bp, tx);
}