summaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2019-06-19 14:54:02 -0700
committerBrian Behlendorf <[email protected]>2019-06-19 14:54:02 -0700
commit050d720c43b6285fc0c30e1e97591f6b796dbd68 (patch)
tree1186ac17585e51e426282f3fd3d114913084fcf3 /cmd
parentfb0be12d7b6db16eabfe8f91da12da7d7854ea9a (diff)
Remove dedupditto functionality
If dedup is in use, the `dedupditto` property can be set, causing ZFS to keep an extra copy of data that is referenced many times (>100x). The idea was that this data is more important than other data and thus we want to be really sure that it is not lost if the disk experiences a small amount of random corruption. ZFS (and system administrators) rely on the pool-level redundancy to protect their data (e.g. mirroring or RAIDZ). Since the user/sysadmin doesn't have control over what data will be offered extra redundancy by dedupditto, this extra redundancy is not very useful. The bulk of the data is still vulnerable to loss based on the pool-level redundancy. For example, if particle strikes corrupt 0.1% of blocks, you will either be saved by mirror/raidz, or you will be sad. This is true even if dedupditto saved another 0.01% of blocks from being corrupted. Therefore, the dedupditto functionality is rarely enabled (i.e. the property is rarely set), and it fulfills its promise of increased redundancy even more rarely. Additionally, this feature does not work as advertised (on existing releases), because scrub/resilver did not repair the extra (dedupditto) copy (see https://github.com/zfsonlinux/zfs/pull/8270). In summary, this seldom-used feature doesn't work, and even if it did it wouldn't provide useful data protection. It has a non-trivial maintenance burden (again see https://github.com/zfsonlinux/zfs/pull/8270). We should remove the dedupditto functionality. For backwards compatibility with the existing CLI, "zpool set dedupditto" will still "succeed" (exit code zero), but won't have any effect. For backwards compatibility with existing pools that had dedupditto enabled at some point, the code will still be able to understand dedupditto blocks and free them when appropriate. However, ZFS won't write any new dedupditto blocks. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Igor Kozhukhov <[email protected]> Reviewed-by: Alek Pinchuk <[email protected]> Issue #8270 Closes #8310
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ztest/ztest.c162
1 files changed, 0 insertions, 162 deletions
diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c
index 22cfa2fe5..a6820dede 100644
--- a/cmd/ztest/ztest.c
+++ b/cmd/ztest/ztest.c
@@ -359,7 +359,6 @@ ztest_func_t ztest_dsl_prop_get_set;
ztest_func_t ztest_spa_prop_get_set;
ztest_func_t ztest_spa_create_destroy;
ztest_func_t ztest_fault_inject;
-ztest_func_t ztest_ddt_repair;
ztest_func_t ztest_dmu_snapshot_hold;
ztest_func_t ztest_mmp_enable_disable;
ztest_func_t ztest_scrub;
@@ -414,7 +413,6 @@ ztest_info_t ztest_info[] = {
ZTI_INIT(ztest_dmu_snapshot_create_destroy, 1, &zopt_sometimes),
ZTI_INIT(ztest_spa_create_destroy, 1, &zopt_sometimes),
ZTI_INIT(ztest_fault_inject, 1, &zopt_sometimes),
- ZTI_INIT(ztest_ddt_repair, 1, &zopt_sometimes),
ZTI_INIT(ztest_dmu_snapshot_hold, 1, &zopt_sometimes),
ZTI_INIT(ztest_mmp_enable_disable, 1, &zopt_sometimes),
ZTI_INIT(ztest_reguid, 1, &zopt_rarely),
@@ -1524,31 +1522,6 @@ ztest_tx_assign(dmu_tx_t *tx, uint64_t txg_how, const char *tag)
}
static void
-ztest_pattern_set(void *buf, uint64_t size, uint64_t value)
-{
- uint64_t *ip = buf;
- uint64_t *ip_end = (uint64_t *)((uintptr_t)buf + (uintptr_t)size);
-
- while (ip < ip_end)
- *ip++ = value;
-}
-
-#ifndef NDEBUG
-static boolean_t
-ztest_pattern_match(void *buf, uint64_t size, uint64_t value)
-{
- uint64_t *ip = buf;
- uint64_t *ip_end = (uint64_t *)((uintptr_t)buf + (uintptr_t)size);
- uint64_t diff = 0;
-
- while (ip < ip_end)
- diff |= (value - *ip++);
-
- return (diff == 0);
-}
-#endif
-
-static void
ztest_bt_generate(ztest_block_tag_t *bt, objset_t *os, uint64_t object,
uint64_t dnodesize, uint64_t offset, uint64_t gen, uint64_t txg,
uint64_t crtxg)
@@ -5574,9 +5547,6 @@ ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
(void) pthread_rwlock_rdlock(&ztest_name_lock);
- (void) ztest_spa_prop_set_uint64(ZPOOL_PROP_DEDUPDITTO,
- ZIO_DEDUPDITTO_MIN + ztest_random(ZIO_DEDUPDITTO_MIN));
-
(void) ztest_spa_prop_set_uint64(ZPOOL_PROP_AUTOTRIM, ztest_random(2));
VERIFY0(spa_prop_get(ztest_spa, &props));
@@ -6018,136 +5988,6 @@ out:
}
/*
- * Verify that DDT repair works as expected.
- */
-void
-ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
-{
- ztest_shared_t *zs = ztest_shared;
- spa_t *spa = ztest_spa;
- objset_t *os = zd->zd_os;
- ztest_od_t *od;
- uint64_t object, blocksize, txg, pattern;
- enum zio_checksum checksum = spa_dedup_checksum(spa);
- dmu_buf_t *db;
- dmu_tx_t *tx;
-
- od = umem_alloc(sizeof (ztest_od_t), UMEM_NOFAIL);
- 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));
- return;
- }
-
- /*
- * Take the name lock as writer to prevent anyone else from changing
- * the pool and dataset properties we need to maintain during this test.
- */
- (void) pthread_rwlock_wrlock(&ztest_name_lock);
-
- if (ztest_dsl_prop_set_uint64(zd->zd_name, ZFS_PROP_DEDUP, checksum,
- B_FALSE) != 0 ||
- ztest_dsl_prop_set_uint64(zd->zd_name, ZFS_PROP_COPIES, 1,
- B_FALSE) != 0) {
- (void) pthread_rwlock_unlock(&ztest_name_lock);
- umem_free(od, sizeof (ztest_od_t));
- return;
- }
-
- dmu_objset_stats_t dds;
- dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
- dmu_objset_fast_stat(os, &dds);
- dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
-
- object = od[0].od_object;
- 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);
- dmu_tx_hold_write(tx, object, 0, copies * blocksize);
- txg = ztest_tx_assign(tx, TXG_WAIT, FTAG);
- if (txg == 0) {
- (void) pthread_rwlock_unlock(&ztest_name_lock);
- umem_free(od, sizeof (ztest_od_t));
- return;
- }
-
- /*
- * Write all the copies of our block.
- */
- 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);
- if (error != 0) {
- fatal(B_FALSE, "dmu_buf_hold(%p, %llu, %llu) = %u",
- os, (long long)object, (long long) offset, error);
- }
- ASSERT(db->db_offset == offset);
- ASSERT(db->db_size == blocksize);
- ASSERT(ztest_pattern_match(db->db_data, db->db_size, pattern) ||
- ztest_pattern_match(db->db_data, db->db_size, 0ULL));
- dmu_buf_will_fill(db, tx);
- ztest_pattern_set(db->db_data, db->db_size, pattern);
- dmu_buf_rele(db, FTAG);
- }
-
- dmu_tx_commit(tx);
- txg_wait_synced(spa_get_dsl(spa), txg);
-
- /*
- * Find out what block we got.
- */
- 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.
- */
- 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,
- abd, psize, NULL, NULL, ZIO_PRIORITY_SYNC_WRITE,
- ZIO_FLAG_CANFAIL | ZIO_FLAG_INDUCE_DAMAGE, NULL));
-
- abd_free(abd);
-
- (void) pthread_rwlock_unlock(&ztest_name_lock);
- umem_free(od, sizeof (ztest_od_t));
-}
-
-/*
* By design ztest will never inject uncorrectable damage in to the pool.
* Issue a scrub, wait for it to complete, and verify there is never any
* any persistent damage.
@@ -7103,8 +6943,6 @@ ztest_run(ztest_shared_t *zs)
zs->zs_guid = dds.dds_guid;
dmu_objset_disown(os, B_TRUE, FTAG);
- spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
-
/*
* Create a thread to periodically resume suspended I/O.
*/