Fix livelist assertions for dedup and cloning
Two block pointers in livelist pointing to the same location may be caused not only by dedup, but also by block cloning. We should not assert D bit set in them. Two block pointers in livelist pointing to the same location may have different logical birth time in case of dedup or cloning. We should assert identical physical birth time instead. Assert identical physical block size between pointers in addition to checksum, since that is what checksums are calculated on. Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #15732
This commit is contained in:
parent
255741fc97
commit
e78aca3b33
|
@ -1000,8 +1000,6 @@ livelist_compare(const void *larg, const void *rarg)
|
||||||
/* if vdevs are equal, sort by offsets. */
|
/* if vdevs are equal, sort by offsets. */
|
||||||
uint64_t l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]);
|
uint64_t l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]);
|
||||||
uint64_t r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]);
|
uint64_t r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]);
|
||||||
if (l_dva0_offset == r_dva0_offset)
|
|
||||||
ASSERT3U(l->blk_birth, ==, r->blk_birth);
|
|
||||||
return (TREE_CMP(l_dva0_offset, r_dva0_offset));
|
return (TREE_CMP(l_dva0_offset, r_dva0_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,9 +1014,9 @@ struct livelist_iter_arg {
|
||||||
* and used to match up ALLOC/FREE pairs. ALLOC'd blkptrs without a
|
* and used to match up ALLOC/FREE pairs. ALLOC'd blkptrs without a
|
||||||
* corresponding FREE are stored in the supplied bplist.
|
* corresponding FREE are stored in the supplied bplist.
|
||||||
*
|
*
|
||||||
* Note that multiple FREE and ALLOC entries for the same blkptr may
|
* Note that multiple FREE and ALLOC entries for the same blkptr may be
|
||||||
* be encountered when dedup is involved. For this reason we keep a
|
* encountered when dedup or block cloning is involved. For this reason we
|
||||||
* refcount for all the FREE entries of each blkptr and ensure that
|
* keep a refcount for all the FREE entries of each blkptr and ensure that
|
||||||
* each of those FREE entries has a corresponding ALLOC preceding it.
|
* each of those FREE entries has a corresponding ALLOC preceding it.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
@ -1037,6 +1035,13 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed,
|
||||||
livelist_entry_t node;
|
livelist_entry_t node;
|
||||||
node.le_bp = *bp;
|
node.le_bp = *bp;
|
||||||
livelist_entry_t *found = avl_find(avl, &node, NULL);
|
livelist_entry_t *found = avl_find(avl, &node, NULL);
|
||||||
|
if (found) {
|
||||||
|
ASSERT3U(BP_GET_PSIZE(bp), ==, BP_GET_PSIZE(&found->le_bp));
|
||||||
|
ASSERT3U(BP_GET_CHECKSUM(bp), ==,
|
||||||
|
BP_GET_CHECKSUM(&found->le_bp));
|
||||||
|
ASSERT3U(BP_PHYSICAL_BIRTH(bp), ==,
|
||||||
|
BP_PHYSICAL_BIRTH(&found->le_bp));
|
||||||
|
}
|
||||||
if (bp_freed) {
|
if (bp_freed) {
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
/* first free entry for this blkptr */
|
/* first free entry for this blkptr */
|
||||||
|
@ -1046,10 +1051,10 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed,
|
||||||
e->le_refcnt = 1;
|
e->le_refcnt = 1;
|
||||||
avl_add(avl, e);
|
avl_add(avl, e);
|
||||||
} else {
|
} else {
|
||||||
/* dedup block free */
|
/*
|
||||||
ASSERT(BP_GET_DEDUP(bp));
|
* Deduped or cloned block free. We could assert D bit
|
||||||
ASSERT3U(BP_GET_CHECKSUM(bp), ==,
|
* for dedup, but there is no such one for cloning.
|
||||||
BP_GET_CHECKSUM(&found->le_bp));
|
*/
|
||||||
ASSERT3U(found->le_refcnt + 1, >, found->le_refcnt);
|
ASSERT3U(found->le_refcnt + 1, >, found->le_refcnt);
|
||||||
found->le_refcnt++;
|
found->le_refcnt++;
|
||||||
}
|
}
|
||||||
|
@ -1065,14 +1070,6 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed,
|
||||||
/* all tracked free pairs have been matched */
|
/* all tracked free pairs have been matched */
|
||||||
avl_remove(avl, found);
|
avl_remove(avl, found);
|
||||||
kmem_free(found, sizeof (livelist_entry_t));
|
kmem_free(found, sizeof (livelist_entry_t));
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* This is definitely a deduped blkptr so
|
|
||||||
* let's validate it.
|
|
||||||
*/
|
|
||||||
ASSERT(BP_GET_DEDUP(bp));
|
|
||||||
ASSERT3U(BP_GET_CHECKSUM(bp), ==,
|
|
||||||
BP_GET_CHECKSUM(&found->le_bp));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue