summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/ztest/ztest.c49
-rw-r--r--module/zfs/ddt.c9
2 files changed, 41 insertions, 17 deletions
diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c
index 3686fab76..da763d74d 100644
--- a/cmd/ztest/ztest.c
+++ b/cmd/ztest/ztest.c
@@ -5993,20 +5993,13 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
spa_t *spa = ztest_spa;
objset_t *os = zd->zd_os;
ztest_od_t *od;
- uint64_t object, blocksize, txg, pattern, psize;
+ uint64_t object, blocksize, txg, pattern;
enum zio_checksum checksum = spa_dedup_checksum(spa);
dmu_buf_t *db;
dmu_tx_t *tx;
- abd_t *abd;
- blkptr_t blk;
- int copies = 2 * ZIO_DEDUPDITTO_MIN;
- int i;
-
- blocksize = ztest_random_blocksize();
- blocksize = MIN(blocksize, 2048); /* because we write so many */
od = umem_alloc(sizeof (ztest_od_t), UMEM_NOFAIL);
- ztest_od_init(od, id, FTAG, 0, DMU_OT_UINT64_OTHER, blocksize, 0, 0);
+ ztest_od_init(od, id, FTAG, 0, DMU_OT_UINT64_OTHER, 0, 0, 0);
if (ztest_object_init(zd, od, sizeof (ztest_od_t), B_FALSE) != 0) {
umem_free(od, sizeof (ztest_od_t));
@@ -6015,7 +6008,7 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
/*
* Take the name lock as writer to prevent anyone else from changing
- * the pool and dataset properies we need to maintain during this test.
+ * the pool and dataset properties we need to maintain during this test.
*/
(void) pthread_rwlock_wrlock(&ztest_name_lock);
@@ -6037,6 +6030,31 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
blocksize = od[0].od_blocksize;
pattern = zs->zs_guid ^ dds.dds_guid;
+ /*
+ * The numbers of copies written must always be greater than or
+ * equal to the threshold set by the dedupditto property. This
+ * is initialized in ztest_run() and then randomly changed by
+ * ztest_spa_prop_get_set(), these function will never set it
+ * larger than 2 * ZIO_DEDUPDITTO_MIN.
+ */
+ int copies = 2 * ZIO_DEDUPDITTO_MIN;
+
+ /*
+ * The block size is limited by DMU_MAX_ACCESS (64MB) which
+ * caps the maximum transaction size. A block size of up to
+ * SPA_OLD_MAXBLOCKSIZE is allowed which results in a maximum
+ * transaction size of: 128K * 200 (copies) = ~25MB
+ *
+ * The actual block size is checked here, rather than requested
+ * above, because the way ztest_od_init() is implemented it does
+ * not guarantee the block size requested will be used.
+ */
+ if (blocksize > SPA_OLD_MAXBLOCKSIZE) {
+ (void) pthread_rwlock_unlock(&ztest_name_lock);
+ umem_free(od, sizeof (ztest_od_t));
+ return;
+ }
+
ASSERT(object != 0);
tx = dmu_tx_create(os);
@@ -6051,7 +6069,7 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
/*
* Write all the copies of our block.
*/
- for (i = 0; i < copies; i++) {
+ for (int i = 0; i < copies; i++) {
uint64_t offset = i * blocksize;
int error = dmu_buf_hold(os, object, offset, FTAG, &db,
DMU_READ_NO_PREFETCH);
@@ -6074,16 +6092,15 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
/*
* Find out what block we got.
*/
- VERIFY0(dmu_buf_hold(os, object, 0, FTAG, &db,
- DMU_READ_NO_PREFETCH));
- blk = *((dmu_buf_impl_t *)db)->db_blkptr;
+ VERIFY0(dmu_buf_hold(os, object, 0, FTAG, &db, DMU_READ_NO_PREFETCH));
+ blkptr_t blk = *((dmu_buf_impl_t *)db)->db_blkptr;
dmu_buf_rele(db, FTAG);
/*
* Damage the block. Dedup-ditto will save us when we read it later.
*/
- psize = BP_GET_PSIZE(&blk);
- abd = abd_alloc_linear(psize, B_TRUE);
+ uint64_t psize = BP_GET_PSIZE(&blk);
+ abd_t *abd = abd_alloc_linear(psize, B_TRUE);
ztest_pattern_set(abd_to_buf(abd), psize, ~pattern);
(void) zio_wait(zio_rewrite(NULL, spa, 0, &blk,
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);
}