Print this page
NEX-3165 need some dedup improvements
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
re #12611 rb4105 zpool import panic in ddt_zap_count()
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
@@ -18,10 +18,11 @@
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
#ifndef _SYS_DDT_H
#define _SYS_DDT_H
@@ -54,10 +55,21 @@
DDT_CLASS_DUPLICATE,
DDT_CLASS_UNIQUE,
DDT_CLASSES
};
+/*
+ * Tracks whether a DDE is loading or already loaded and
+ * which entries got removed from dedup path to support dedup ceiling
+ */
+enum dde_state {
+ DDE_LOADING = (1 << 0),
+ DDE_LOADED = (1 << 1),
+ DDE_NEW = (1 << 2),
+ DDE_DONT_SYNC = (1 << 3),
+};
+
#define DDT_TYPE_CURRENT 0
#define DDT_COMPRESS_BYTEORDER_MASK 0x80
#define DDT_COMPRESS_FUNCTION_MASK 0x7f
@@ -109,25 +121,31 @@
*/
struct ddt_entry {
ddt_key_t dde_key;
ddt_phys_t dde_phys[DDT_PHYS_TYPES];
zio_t *dde_lead_zio[DDT_PHYS_TYPES];
+ ddt_stat_t dde_lkstat;
struct abd *dde_repair_abd;
enum ddt_type dde_type;
enum ddt_class dde_class;
- uint8_t dde_loading;
- uint8_t dde_loaded;
+ uint8_t dde_state;
kcondvar_t dde_cv;
+ kmutex_t dde_lock;
avl_node_t dde_node;
};
+#define DDT_HASHSZ 0x100
+#define DDT_HASHFN(csum) (*((uint8_t *)&(csum).zc_word[0]) & \
+ (DDT_HASHSZ - 1))
+
/*
* In-core ddt
*/
struct ddt {
- kmutex_t ddt_lock;
- avl_tree_t ddt_tree;
+ kmutex_t ddt_lock[DDT_HASHSZ];
+ avl_tree_t ddt_tree[DDT_HASHSZ];
+ kmutex_t ddt_repair_lock;
avl_tree_t ddt_repair_tree;
enum zio_checksum ddt_checksum;
spa_t *ddt_spa;
objset_t *ddt_os;
uint64_t ddt_stat_object;
@@ -163,21 +181,21 @@
dmu_tx_t *tx);
int (*ddt_op_remove)(objset_t *os, uint64_t object, ddt_entry_t *dde,
dmu_tx_t *tx);
int (*ddt_op_walk)(objset_t *os, uint64_t object, ddt_entry_t *dde,
uint64_t *walk);
- uint64_t (*ddt_op_count)(objset_t *os, uint64_t object);
+ int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
} ddt_ops_t;
#define DDT_NAMELEN 80
extern void ddt_object_name(ddt_t *ddt, enum ddt_type type,
enum ddt_class class, char *name);
extern int ddt_object_walk(ddt_t *ddt, enum ddt_type type,
enum ddt_class class, uint64_t *walk, ddt_entry_t *dde);
-extern uint64_t ddt_object_count(ddt_t *ddt, enum ddt_type type,
- enum ddt_class class);
+extern int ddt_object_count(ddt_t *ddt, enum ddt_type type,
+ enum ddt_class class, uint64_t *count);
extern int ddt_object_info(ddt_t *ddt, enum ddt_type type,
enum ddt_class class, dmu_object_info_t *);
extern boolean_t ddt_object_exists(ddt_t *ddt, enum ddt_type type,
enum ddt_class class);
@@ -215,12 +233,14 @@
extern size_t ddt_compress(void *src, uchar_t *dst, size_t s_len, size_t d_len);
extern void ddt_decompress(uchar_t *src, void *dst, size_t s_len, size_t d_len);
extern ddt_t *ddt_select(spa_t *spa, const blkptr_t *bp);
-extern void ddt_enter(ddt_t *ddt);
-extern void ddt_exit(ddt_t *ddt);
+extern void ddt_enter(ddt_t *ddt, uint8_t hash);
+extern void ddt_exit(ddt_t *ddt, uint8_t hash);
+extern void dde_enter(ddt_entry_t *dde);
+extern void dde_exit(ddt_entry_t *dde);
extern ddt_entry_t *ddt_lookup(ddt_t *ddt, const blkptr_t *bp, boolean_t add);
extern void ddt_prefetch(spa_t *spa, const blkptr_t *bp);
extern void ddt_remove(ddt_t *ddt, ddt_entry_t *dde);
extern boolean_t ddt_class_contains(spa_t *spa, enum ddt_class max_class,
@@ -236,10 +256,12 @@
extern void ddt_unload(spa_t *spa);
extern void ddt_sync(spa_t *spa, uint64_t txg);
extern int ddt_walk(spa_t *spa, ddt_bookmark_t *ddb, ddt_entry_t *dde);
extern int ddt_object_update(ddt_t *ddt, enum ddt_type type,
enum ddt_class class, ddt_entry_t *dde, dmu_tx_t *tx);
+extern void ddt_init(void);
+extern void ddt_fini(void);
extern const ddt_ops_t ddt_zap_ops;
#ifdef __cplusplus
}