From 325d288c5d536227010ff4dfcf66df89f123d166 Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Tue, 20 Aug 2019 11:34:52 -0700 Subject: 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 Reviewed-by: Brian Behlendorf Reviewed-by: Paul Dagnelie Signed-off-by: Matthew Ahrens External-issue: DLPX-58348 Closes #8744 --- include/sys/dsl_deadlist.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'include/sys') 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 } -- cgit v1.2.3