diff options
author | Brian Behlendorf <[email protected]> | 2015-12-11 11:09:41 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2015-12-15 16:12:31 -0800 |
commit | eba9e745dcfce252fc6c451cdf07c55bf975f1f6 (patch) | |
tree | 4b625a4111eaf9c5d971649e3cf08bf1cfeed2e2 | |
parent | 1cdb86cba2750f6da468e021a5ae2ba9a24530df (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.c | 8 |
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); } |