summaryrefslogtreecommitdiffstats
path: root/module/zfs/ddt.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2019-01-17 15:25:00 -0800
committerGitHub <[email protected]>2019-01-17 15:25:00 -0800
commit52b684236d35c64bb371bd19ce0c87552e368d77 (patch)
treefaaa0151b63e4ade0ec119467e2a9f3698a6918a /module/zfs/ddt.c
parent419ba5914552c6185afbe1dd17b3ed4b0d526547 (diff)
ztest: scrub ddt repair
The ztest_ddt_repair() test is designed inflict damage to the ddt which can be repairable by a scrub. Unfortunately, this repair logic was broken at some point and it went undetected. This issue is not specific to ztest, but thankfully this extra redundancy is rarely enabled and even more rarely needed. The root cause was identified to be the ddt_bp_create() function called by dsl_scan_ddt_entry() which did not set the dedup bit of the generated block pointer. The consequence of this was that the ZIO_DDT_READ_PIPELINE was never enabled for the block pointer during the scrub, and the dedup ditto repair logic was never run. Note that for demand reads which don't rely on ddt_bp_create() the required pipeline stages would be enabled and the repair performed. This was resolved by unconditionally setting the dedup bit in ddt_bp_create(). This way all codes paths which may need to perform a repair from a block pointer generated from the dtt entry will be able too. The only exception is that the dedup bit is cleared in ddt_phys_free() which is required to avoid leaking space. Reviewed by: Matt Ahrens <[email protected]> Reviewed by: Tom Caputi <[email protected]> Reviewed by: Serapheim Dimitropoulos <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #8270
Diffstat (limited to 'module/zfs/ddt.c')
-rw-r--r--module/zfs/ddt.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c
index f7fe2ae80..a38c2b24e 100644
--- a/module/zfs/ddt.c
+++ b/module/zfs/ddt.c
@@ -291,7 +291,7 @@ ddt_bp_create(enum zio_checksum checksum,
BP_SET_CHECKSUM(bp, checksum);
BP_SET_TYPE(bp, DMU_OT_DEDUP);
BP_SET_LEVEL(bp, 0);
- BP_SET_DEDUP(bp, 0);
+ BP_SET_DEDUP(bp, 1);
BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER);
}
@@ -346,6 +346,13 @@ ddt_phys_free(ddt_t *ddt, ddt_key_t *ddk, ddt_phys_t *ddp, uint64_t txg)
blkptr_t blk;
ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
+
+ /*
+ * We clear the dedup bit so that zio_free() will actually free the
+ * space, rather than just decrementing the refcount in the DDT.
+ */
+ BP_SET_DEDUP(&blk, 0);
+
ddt_phys_clear(ddp);
zio_free(ddt->ddt_spa, txg, &blk);
}