aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/dsl_destroy.c
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 /module/zfs/dsl_destroy.c
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 'module/zfs/dsl_destroy.c')
-rw-r--r--module/zfs/dsl_destroy.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/module/zfs/dsl_destroy.c b/module/zfs/dsl_destroy.c
index 5c483c5dd..788753bdc 100644
--- a/module/zfs/dsl_destroy.c
+++ b/module/zfs/dsl_destroy.c
@@ -413,6 +413,13 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
/* Merge our deadlist into next's and free it. */
dsl_deadlist_merge(&ds_next->ds_deadlist,
dsl_dataset_phys(ds)->ds_deadlist_obj, tx);
+
+ /*
+ * We are done with the deadlist tree (generated/used
+ * by dsl_deadlist_move_bpobj() and dsl_deadlist_merge()).
+ * Discard it to save memory.
+ */
+ dsl_deadlist_discard_tree(&ds_next->ds_deadlist);
}
dsl_deadlist_close(&ds->ds_deadlist);