aboutsummaryrefslogtreecommitdiffstats
path: root/include/sys
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2019-08-20 11:34:52 -0700
committerBrian Behlendorf <[email protected]>2019-08-20 11:34:52 -0700
commit325d288c5d536227010ff4dfcf66df89f123d166 (patch)
tree86807360e97638a06b6cce82a168b75a36a3caaf /include/sys
parent3beb0a7694df5d1d4314179147aaa1d40b63fe76 (diff)
Add fast path for zfs_ioc_space_snaps() handling of empty_bpobj
When there are many snapshots, calls to zfs_ioc_space_snaps() (e.g. from `zfs destroy -nv pool/fs@snap1%snap10000`) can be very slow, resulting in poor performance because we are holding the dp_config_rwlock the entire time, blocking spa_sync() from continuing. With around ten thousand snapshots, we've seen up to 500 seconds in this ioctl, iterating over up to 50,000,000 bpobjs, ~99% of which are the empty bpobj. By creating a fast path for zfs_ioc_space_snaps() handling of the empty_bpobj, we can achieve a ~5x performance improvement of this ioctl (when there are many snapshots, and the deadlist is mostly empty_bpobj's). Reviewed-by: Pavel Zakharov <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Paul Dagnelie <[email protected]> Signed-off-by: Matthew Ahrens <[email protected]> External-issue: DLPX-58348 Closes #8744
Diffstat (limited to 'include/sys')
-rw-r--r--include/sys/dsl_deadlist.h14
1 files changed, 13 insertions, 1 deletions
diff --git a/include/sys/dsl_deadlist.h b/include/sys/dsl_deadlist.h
index bb8248a66..64358bb5f 100644
--- a/include/sys/dsl_deadlist.h
+++ b/include/sys/dsl_deadlist.h
@@ -48,8 +48,10 @@ typedef struct dsl_deadlist_phys {
typedef struct dsl_deadlist {
objset_t *dl_os;
uint64_t dl_object;
- avl_tree_t dl_tree;
+ avl_tree_t dl_tree; /* contains dsl_deadlist_entry_t */
+ avl_tree_t dl_cache; /* contains dsl_deadlist_cache_entry_t */
boolean_t dl_havetree;
+ boolean_t dl_havecache;
struct dmu_buf *dl_dbuf;
dsl_deadlist_phys_t *dl_phys;
kmutex_t dl_lock;
@@ -59,6 +61,15 @@ typedef struct dsl_deadlist {
boolean_t dl_oldfmt;
} dsl_deadlist_t;
+typedef struct dsl_deadlist_cache_entry {
+ avl_node_t dlce_node;
+ uint64_t dlce_mintxg;
+ uint64_t dlce_bpobj;
+ uint64_t dlce_bytes;
+ uint64_t dlce_comp;
+ uint64_t dlce_uncomp;
+} dsl_deadlist_cache_entry_t;
+
typedef struct dsl_deadlist_entry {
avl_node_t dle_node;
uint64_t dle_mintxg;
@@ -108,6 +119,7 @@ int dsl_process_sub_livelist(bpobj_t *bpobj, struct bplist *to_free,
zthr_t *t, uint64_t *size);
void dsl_deadlist_clear_entry(dsl_deadlist_entry_t *dle, dsl_deadlist_t *dl,
dmu_tx_t *tx);
+void dsl_deadlist_discard_tree(dsl_deadlist_t *dl);
#ifdef __cplusplus
}