aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/ddt.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/ddt.c')
-rw-r--r--module/zfs/ddt.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c
index 7880a899a..33fea0ba3 100644
--- a/module/zfs/ddt.c
+++ b/module/zfs/ddt.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2022 by Pawel Jakub Dawidek
*/
#include <sys/zfs_context.h>
@@ -1180,5 +1181,59 @@ ddt_walk(spa_t *spa, ddt_bookmark_t *ddb, ddt_entry_t *dde)
return (SET_ERROR(ENOENT));
}
+/*
+ * This function is used by Block Cloning (brt.c) to increase reference
+ * counter for the DDT entry if the block is already in DDT.
+ *
+ * Return false if the block, despite having the D bit set, is not present
+ * in the DDT. Currently this is not possible but might be in the future.
+ * See the comment below.
+ */
+boolean_t
+ddt_addref(spa_t *spa, const blkptr_t *bp)
+{
+ ddt_t *ddt;
+ ddt_entry_t *dde;
+ boolean_t result;
+
+ spa_config_enter(spa, SCL_ZIO, FTAG, RW_READER);
+ ddt = ddt_select(spa, bp);
+ ddt_enter(ddt);
+
+ dde = ddt_lookup(ddt, bp, B_TRUE);
+ ASSERT(dde != NULL);
+
+ if (dde->dde_type < DDT_TYPES) {
+ ddt_phys_t *ddp;
+
+ ASSERT3S(dde->dde_class, <, DDT_CLASSES);
+
+ ddp = &dde->dde_phys[BP_GET_NDVAS(bp)];
+ if (ddp->ddp_refcnt == 0) {
+ /* This should never happen? */
+ ddt_phys_fill(ddp, bp);
+ }
+ ddt_phys_addref(ddp);
+ result = B_TRUE;
+ } else {
+ /*
+ * At the time of implementating this if the block has the
+ * DEDUP flag set it must exist in the DEDUP table, but
+ * there are many advocates that want ability to remove
+ * entries from DDT with refcnt=1. If this will happen,
+ * we may have a block with the DEDUP set, but which doesn't
+ * have a corresponding entry in the DDT. Be ready.
+ */
+ ASSERT3S(dde->dde_class, ==, DDT_CLASSES);
+ ddt_remove(ddt, dde);
+ result = B_FALSE;
+ }
+
+ ddt_exit(ddt);
+ spa_config_exit(spa, SCL_ZIO, FTAG);
+
+ return (result);
+}
+
ZFS_MODULE_PARAM(zfs_dedup, zfs_dedup_, prefetch, INT, ZMOD_RW,
"Enable prefetching dedup-ed blks");