]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - zfs/module/zfs/ddt.c
UBUNTU: SAUCE: (noup) Update spl to 0.7.3-1ubuntu1, zfs to 0.7.3-1ubuntu1
[mirror_ubuntu-bionic-kernel.git] / zfs / module / zfs / ddt.c
index 12c1b7300a2136e088806d8b83a25791578981cd..75ab7f5b26e134e9de5c1dab9175902d57a05a2d 100644 (file)
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -36,6 +36,7 @@
 #include <sys/zio_checksum.h>
 #include <sys/zio_compress.h>
 #include <sys/dsl_scan.h>
+#include <sys/abd.h>
 
 static kmem_cache_t *ddt_cache;
 static kmem_cache_t *ddt_entry_cache;
@@ -62,7 +63,8 @@ ddt_object_create(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
        spa_t *spa = ddt->ddt_spa;
        objset_t *os = ddt->ddt_os;
        uint64_t *objectp = &ddt->ddt_object[type][class];
-       boolean_t prehash = zio_checksum_table[ddt->ddt_checksum].ci_dedup;
+       boolean_t prehash = zio_checksum_table[ddt->ddt_checksum].ci_flags &
+           ZCHECKSUM_FLAG_DEDUP;
        char name[DDT_NAMELEN];
 
        ddt_object_name(ddt, type, class, name);
@@ -527,10 +529,17 @@ ddt_get_dedup_stats(spa_t *spa, ddt_stat_t *dds_total)
 uint64_t
 ddt_get_dedup_dspace(spa_t *spa)
 {
-       ddt_stat_t dds_total = { 0 };
+       ddt_stat_t dds_total;
+
+       if (spa->spa_dedup_dspace != ~0ULL)
+               return (spa->spa_dedup_dspace);
+
+       bzero(&dds_total, sizeof (ddt_stat_t));
 
+       /* Calculate and cache the stats */
        ddt_get_dedup_stats(spa, &dds_total);
-       return (dds_total.dds_ref_dsize - dds_total.dds_dsize);
+       spa->spa_dedup_dspace = dds_total.dds_ref_dsize - dds_total.dds_dsize;
+       return (spa->spa_dedup_dspace);
 }
 
 uint64_t
@@ -705,9 +714,8 @@ ddt_free(ddt_entry_t *dde)
        for (p = 0; p < DDT_PHYS_TYPES; p++)
                ASSERT(dde->dde_lead_zio[p] == NULL);
 
-       if (dde->dde_repair_data != NULL)
-               zio_buf_free(dde->dde_repair_data,
-                   DDK_GET_PSIZE(&dde->dde_key));
+       if (dde->dde_repair_abd != NULL)
+               abd_free(dde->dde_repair_abd);
 
        cv_destroy(&dde->dde_cv);
        kmem_cache_free(ddt_entry_cache, dde);
@@ -811,23 +819,32 @@ ddt_prefetch(spa_t *spa, const blkptr_t *bp)
        }
 }
 
+/*
+ * Opaque struct used for ddt_key comparison
+ */
+#define        DDT_KEY_CMP_LEN (sizeof (ddt_key_t) / sizeof (uint16_t))
+
+typedef struct ddt_key_cmp {
+       uint16_t        u16[DDT_KEY_CMP_LEN];
+} ddt_key_cmp_t;
+
 int
 ddt_entry_compare(const void *x1, const void *x2)
 {
        const ddt_entry_t *dde1 = x1;
        const ddt_entry_t *dde2 = x2;
-       const uint64_t *u1 = (const uint64_t *)&dde1->dde_key;
-       const uint64_t *u2 = (const uint64_t *)&dde2->dde_key;
+       const ddt_key_cmp_t *k1 = (const ddt_key_cmp_t *)&dde1->dde_key;
+       const ddt_key_cmp_t *k2 = (const ddt_key_cmp_t *)&dde2->dde_key;
+       int32_t cmp = 0;
        int i;
 
-       for (i = 0; i < DDT_KEY_WORDS; i++) {
-               if (u1[i] < u2[i])
-                       return (-1);
-               if (u1[i] > u2[i])
-                       return (1);
+       for (i = 0; i < DDT_KEY_CMP_LEN; i++) {
+               cmp = (int32_t)k1->u16[i] - (int32_t)k2->u16[i];
+               if (likely(cmp))
+                       break;
        }
 
-       return (0);
+       return (AVL_ISIGN(cmp));
 }
 
 static ddt_t *
@@ -905,6 +922,7 @@ ddt_load(spa_t *spa)
                 */
                bcopy(ddt->ddt_histogram, &ddt->ddt_histogram_cache,
                    sizeof (ddt->ddt_histogram));
+               spa->spa_dedup_dspace = ~0ULL;
        }
 
        return (0);
@@ -992,7 +1010,7 @@ ddt_repair_done(ddt_t *ddt, ddt_entry_t *dde)
 
        ddt_enter(ddt);
 
-       if (dde->dde_repair_data != NULL && spa_writeable(ddt->ddt_spa) &&
+       if (dde->dde_repair_abd != NULL && spa_writeable(ddt->ddt_spa) &&
            avl_find(&ddt->ddt_repair_tree, dde, &where) == NULL)
                avl_insert(&ddt->ddt_repair_tree, dde, where);
        else
@@ -1030,7 +1048,7 @@ ddt_repair_entry(ddt_t *ddt, ddt_entry_t *dde, ddt_entry_t *rdde, zio_t *rio)
                        continue;
                ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
                zio_nowait(zio_rewrite(zio, zio->io_spa, 0, &blk,
-                   rdde->dde_repair_data, DDK_GET_PSIZE(rddk), NULL, NULL,
+                   rdde->dde_repair_abd, DDK_GET_PSIZE(rddk), NULL, NULL,
                    ZIO_PRIORITY_SYNC_WRITE, ZIO_DDT_CHILD_FLAGS(zio), NULL));
        }
 
@@ -1172,6 +1190,7 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg)
 
        bcopy(ddt->ddt_histogram, &ddt->ddt_histogram_cache,
            sizeof (ddt->ddt_histogram));
+       spa->spa_dedup_dspace = ~0ULL;
 }
 
 void