Fix deduplication of overridden blocks

Implementation of DDT pruning introduced verification of DVAs in
a block pointer during ddt_lookup() to not by mistake free previous
pruned incarnation of the entry.  But when writing a new block in
zio_ddt_write() we might have the DVAs only from override pointer,
which may never have "D" flag to be confused with pruned DDT entry,
and we'll abandon those DVAs if we find a matching entry in DDT.

This fixes deduplication for blocks written via dmu_sync() for
purposes of indirect ZIL write records, that I have tested.  And
I suspect it might actually allow deduplication for Direct I/O,
even though in an odd way -- first write block directly and then
delete it later during TXG commit if found duplicate, which part
I haven't tested.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by:	Alexander Motin <mav@FreeBSD.org>
Sponsored by:	iXsystems, Inc.
Closes #17120
This commit is contained in:
Alexander Motin
2025-03-13 13:27:57 -04:00
committed by GitHub
parent 09f4dd06c3
commit 0ea44e576b
4 changed files with 19 additions and 11 deletions
+8 -2
View File
@@ -3717,7 +3717,13 @@ zio_ddt_write(zio_t *zio)
ASSERT3B(zio->io_prop.zp_direct_write, ==, B_FALSE);
ddt_enter(ddt);
dde = ddt_lookup(ddt, bp);
/*
* Search DDT for matching entry. Skip DVAs verification here, since
* they can go only from override, and once we get here the override
* pointer can't have "D" flag to be confused with pruned DDT entries.
*/
IMPLY(zio->io_bp_override, !BP_GET_DEDUP(zio->io_bp_override));
dde = ddt_lookup(ddt, bp, B_FALSE);
if (dde == NULL) {
/* DDT size is over its quota so no new entries */
zp->zp_dedup = B_FALSE;
@@ -3993,7 +3999,7 @@ zio_ddt_free(zio_t *zio)
ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
ddt_enter(ddt);
freedde = dde = ddt_lookup(ddt, bp);
freedde = dde = ddt_lookup(ddt, bp, B_TRUE);
if (dde) {
ddt_phys_variant_t v = ddt_phys_select(ddt, dde, bp);
if (v != DDT_PHYS_NONE)