summaryrefslogtreecommitdiffstats
path: root/module/zfs/ddt.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2011-05-25 13:56:40 -0700
committerBrian Behlendorf <[email protected]>2011-05-31 12:17:27 -0700
commite95b3bdcbbc64ea502349413234e7c71563e7115 (patch)
tree50792f2a3b7a27d6a65e6f7428e0831e99a92b6f /module/zfs/ddt.c
parent5b8c7bbcea7ad9ecd5f329d2d736cba8402ee781 (diff)
Fix stack ddt_class_contains()
Stack usage for ddt_class_contains() reduced from 524 bytes to 68 bytes. This large stack allocation significantly contributed to the likelyhood of a stack overflow when scrubbing/resilvering dedup pools.
Diffstat (limited to 'module/zfs/ddt.c')
-rw-r--r--module/zfs/ddt.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c
index 49428d109..7279f1d5d 100644
--- a/module/zfs/ddt.c
+++ b/module/zfs/ddt.c
@@ -891,7 +891,7 @@ boolean_t
ddt_class_contains(spa_t *spa, enum ddt_class max_class, const blkptr_t *bp)
{
ddt_t *ddt;
- ddt_entry_t dde;
+ ddt_entry_t *dde;
enum ddt_type type;
enum ddt_class class;
@@ -902,14 +902,20 @@ ddt_class_contains(spa_t *spa, enum ddt_class max_class, const blkptr_t *bp)
return (B_TRUE);
ddt = spa->spa_ddt[BP_GET_CHECKSUM(bp)];
+ dde = kmem_alloc(sizeof(ddt_entry_t), KM_SLEEP);
- ddt_key_fill(&dde.dde_key, bp);
+ ddt_key_fill(&(dde->dde_key), bp);
- for (type = 0; type < DDT_TYPES; type++)
- for (class = 0; class <= max_class; class++)
- if (ddt_object_lookup(ddt, type, class, &dde) == 0)
+ for (type = 0; type < DDT_TYPES; type++) {
+ for (class = 0; class <= max_class; class++) {
+ if (ddt_object_lookup(ddt, type, class, dde) == 0) {
+ kmem_free(dde, sizeof(ddt_entry_t));
return (B_TRUE);
+ }
+ }
+ }
+ kmem_free(dde, sizeof(ddt_entry_t));
return (B_FALSE);
}