From: Brian Behlendorf Date: Fri, 11 Dec 2015 19:09:41 +0000 (-0800) Subject: Handle damaged blk_birth in dsl_deadlist_insert() X-Git-Tag: zfs-0.7.0-rc1~348 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eba9e745dcfce252fc6c451cdf07c55bf975f1f6;p=zfs 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 Signed-off-by: Chunwei Chen Closes #4086 Closes #4089 --- 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); }