mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
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 <pcd@delphix.com> Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Don Brady <don.brady@delphix.com> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc. Closes #12314
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user