Skip to content

Commit b14b3e3

Browse files
authored
Fix FDT rollback to not overwrite unnecessary fields (#17205)
When a dedup write fails, we try to roll the DDT entry back to a known good state. However, this also rolls the refcounts and the last-update time back to the state they were at when we started this write. This doesn't appear to be able to cause any refcount leaks (after the fix in 17123). This PR prevents that from happening by only rolling back the parts of the DDT entry that have been updated by the write so far. Sponsored-by: iXsystems, Inc. Sponsored-by: Klara, Inc. Signed-off-by: Paul Dagnelie <[email protected]> Co-authored-by: Paul Dagnelie <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Tony Hutter <[email protected]>
1 parent c050b73 commit b14b3e3

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

include/sys/ddt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ extern void ddt_bp_create(enum zio_checksum checksum, const ddt_key_t *ddk,
339339

340340
extern void ddt_phys_extend(ddt_univ_phys_t *ddp, ddt_phys_variant_t v,
341341
const blkptr_t *bp);
342+
extern void ddt_phys_unextend(ddt_univ_phys_t *cur, ddt_univ_phys_t *orig,
343+
ddt_phys_variant_t v);
342344
extern void ddt_phys_copy(ddt_univ_phys_t *dst, const ddt_univ_phys_t *src,
343345
ddt_phys_variant_t v);
344346
extern void ddt_phys_clear(ddt_univ_phys_t *ddp, ddt_phys_variant_t v);

module/zfs/ddt.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,27 @@ ddt_phys_extend(ddt_univ_phys_t *ddp, ddt_phys_variant_t v, const blkptr_t *bp)
731731
}
732732
}
733733

734+
void
735+
ddt_phys_unextend(ddt_univ_phys_t *cur, ddt_univ_phys_t *orig,
736+
ddt_phys_variant_t v)
737+
{
738+
ASSERT3U(v, <, DDT_PHYS_NONE);
739+
dva_t *cur_dvas = (v == DDT_PHYS_FLAT) ?
740+
cur->ddp_flat.ddp_dva : cur->ddp_trad[v].ddp_dva;
741+
dva_t *orig_dvas = (v == DDT_PHYS_FLAT) ?
742+
orig->ddp_flat.ddp_dva : orig->ddp_trad[v].ddp_dva;
743+
744+
for (int d = 0; d < SPA_DVAS_PER_BP; d++)
745+
cur_dvas[d] = orig_dvas[d];
746+
747+
if (ddt_phys_birth(orig, v) == 0) {
748+
if (v == DDT_PHYS_FLAT)
749+
cur->ddp_flat.ddp_phys_birth = 0;
750+
else
751+
cur->ddp_trad[v].ddp_phys_birth = 0;
752+
}
753+
}
754+
734755
void
735756
ddt_phys_copy(ddt_univ_phys_t *dst, const ddt_univ_phys_t *src,
736757
ddt_phys_variant_t v)

module/zfs/zio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3607,7 +3607,7 @@ zio_ddt_child_write_done(zio_t *zio)
36073607
* chain. We need to revert the entry back to what it was at
36083608
* the last time it was successfully extended.
36093609
*/
3610-
ddt_phys_copy(ddp, orig, v);
3610+
ddt_phys_unextend(ddp, orig, v);
36113611
ddt_phys_clear(orig, v);
36123612

36133613
ddt_exit(ddt);

0 commit comments

Comments
 (0)