aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAlexander Motin <[email protected]>2021-07-21 08:40:36 -0400
committerTony Hutter <[email protected]>2021-09-14 12:40:15 -0700
commit32c0b6468cbcfbd6c2c4bc08f88f34e016b4f184 (patch)
treed1c1adb19a5db5faee4aa2f32959900632a8e8b0 /include
parent7c61e1ef9d9f6c5fa6a3665a88838a19120cf07b (diff)
Optimize allocation throttling
Remove mc_lock use from metaslab_class_throttle_*(). The math there is based on refcounts and so atomic, so the only race possible there is between zfs_refcount_count() and zfs_refcount_add(). But in most cases metaslab_class_throttle_reserve() is called with the allocator lock held, which covers the race. In cases where the lock is not held, GANG_ALLOCATION() or METASLAB_MUST_RESERVE are set, and so we do not use zfs_refcount_count(). And even if we assume some other non-existing scenario, the worst that may happen from this race is few more I/Os get to allocation earlier, that is not a problem. Move locks and data of different allocators into different cache lines to avoid false sharing. Group spa_alloc_* arrays together into single array of aligned struct spa_alloc spa_allocs. Align struct metaslab_class_allocator. Reviewed-by: Paul Dagnelie <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Reviewed-by: Don Brady <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Closes #12314
Diffstat (limited to 'include')
-rw-r--r--include/sys/metaslab_impl.h2
-rw-r--r--include/sys/spa_impl.h15
2 files changed, 10 insertions, 7 deletions
diff --git a/include/sys/metaslab_impl.h b/include/sys/metaslab_impl.h
index 9924c3ba0..adf4c03a2 100644
--- a/include/sys/metaslab_impl.h
+++ b/include/sys/metaslab_impl.h
@@ -157,7 +157,7 @@ typedef struct metaslab_class_allocator {
*/
uint64_t mca_alloc_max_slots;
zfs_refcount_t mca_alloc_slots;
-} metaslab_class_allocator_t;
+} ____cacheline_aligned metaslab_class_allocator_t;
/*
* A metaslab class encompasses a category of allocatable top-level vdevs.
diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
index bc88cfa15..cb2c49e58 100644
--- a/include/sys/spa_impl.h
+++ b/include/sys/spa_impl.h
@@ -57,6 +57,11 @@
extern "C" {
#endif
+typedef struct spa_alloc {
+ kmutex_t spaa_lock;
+ avl_tree_t spaa_tree;
+} ____cacheline_aligned spa_alloc_t;
+
typedef struct spa_error_entry {
zbookmark_phys_t se_bookmark;
char *se_name;
@@ -250,13 +255,11 @@ struct spa {
list_t spa_config_dirty_list; /* vdevs with dirty config */
list_t spa_state_dirty_list; /* vdevs with dirty state */
/*
- * spa_alloc_locks and spa_alloc_trees are arrays, whose lengths are
- * stored in spa_alloc_count. There is one tree and one lock for each
- * allocator, to help improve allocation performance in write-heavy
- * workloads.
+ * spa_allocs is an array, whose lengths is stored in spa_alloc_count.
+ * There is one tree and one lock for each allocator, to help improve
+ * allocation performance in write-heavy workloads.
*/
- kmutex_t *spa_alloc_locks;
- avl_tree_t *spa_alloc_trees;
+ spa_alloc_t *spa_allocs;
int spa_alloc_count;
spa_aux_vdev_t spa_spares; /* hot spares */