From 992cc30a0d0bc9878a8a115c2f4c1fee8b061abf Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Mon, 12 Oct 2015 12:31:05 -0700 Subject: [PATCH] Fix CPU hotplug Allocate a kmem cache magazine for every possible CPU which might be added to the system. This ensures that when one of these CPUs is enabled it can be safely used immediately. For many systems the number of online CPUs is identical to the number of present CPUs so this does imply an increased memory footprint. In fact, dynamically allocating the array of magazine pointers instead of using the worst case NR_CPUS can end up decreasing our memory footprint. Signed-off-by: Brian Behlendorf --- include/sys/kmem_cache.h | 2 +- module/spl/spl-kmem-cache.c | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/sys/kmem_cache.h b/include/sys/kmem_cache.h index 75a0a55b..e971c2b0 100644 --- a/include/sys/kmem_cache.h +++ b/include/sys/kmem_cache.h @@ -170,7 +170,7 @@ typedef struct spl_kmem_cache { uint32_t skc_magic; /* Sanity magic */ uint32_t skc_name_size; /* Name length */ char *skc_name; /* Name string */ - spl_kmem_magazine_t *skc_mag[NR_CPUS]; /* Per-CPU warm cache */ + spl_kmem_magazine_t **skc_mag; /* Per-CPU warm cache */ uint32_t skc_mag_size; /* Magazine size */ uint32_t skc_mag_refill; /* Magazine refill count */ spl_kmem_ctor_t skc_ctor; /* Constructor */ diff --git a/module/spl/spl-kmem-cache.c b/module/spl/spl-kmem-cache.c index a7f9ca3a..5a8493fe 100644 --- a/module/spl/spl-kmem-cache.c +++ b/module/spl/spl-kmem-cache.c @@ -805,15 +805,18 @@ spl_magazine_create(spl_kmem_cache_t *skc) if (skc->skc_flags & KMC_NOMAGAZINE) return (0); + skc->skc_mag = kzalloc(sizeof (spl_kmem_magazine_t *) * + num_possible_cpus(), kmem_flags_convert(KM_SLEEP)); skc->skc_mag_size = spl_magazine_size(skc); skc->skc_mag_refill = (skc->skc_mag_size + 1) / 2; - for_each_online_cpu(i) { + for_each_possible_cpu(i) { skc->skc_mag[i] = spl_magazine_alloc(skc, i); if (!skc->skc_mag[i]) { for (i--; i >= 0; i--) spl_magazine_free(skc->skc_mag[i]); + kfree(skc->skc_mag); return (-ENOMEM); } } @@ -833,11 +836,13 @@ spl_magazine_destroy(spl_kmem_cache_t *skc) if (skc->skc_flags & KMC_NOMAGAZINE) return; - for_each_online_cpu(i) { + for_each_possible_cpu(i) { skm = skc->skc_mag[i]; spl_cache_flush(skc, skm, skm->skm_avail); spl_magazine_free(skm); } + + kfree(skc->skc_mag); } /* @@ -880,12 +885,6 @@ spl_kmem_cache_create(char *name, size_t size, size_t align, might_sleep(); - /* - * Allocate memory for a new cache and initialize it. Unfortunately, - * this usually ends up being a large allocation of ~32k because - * we need to allocate enough memory for the worst case number of - * cpus in the magazine, skc_mag[NR_CPUS]. - */ skc = kzalloc(sizeof (*skc), lflags); if (skc == NULL) return (NULL);