Remove KMC_KMEM and KMC_VMEM

`KMC_KMEM` and `KMC_VMEM` are now unused since all SPL-implemented
caches are `KMC_KVMEM`.

KMC_KMEM: Given the default value of `spl_kmem_cache_kmem_limit`, we
don't use kmalloc to back the SPL caches, instead we use kvmalloc
(KMC_KVMEM).  The flag, module parameter, /proc entries, and associated
code are removed.

KMC_VMEM: This flag is not used, and kvmalloc() is always preferable to
vmalloc().  The flag, /proc entries, and associated code are removed.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #10673
This commit is contained in:
Matthew Ahrens 2020-08-17 16:04:28 -07:00 committed by GitHub
parent 3df0c2fa32
commit 994de7e4b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 10 additions and 151 deletions

View File

@ -37,8 +37,6 @@
*/
typedef enum kmc_bit {
KMC_BIT_NODEBUG = 1, /* Default behavior */
KMC_BIT_KMEM = 5, /* Use kmem cache */
KMC_BIT_VMEM = 6, /* Use vmem cache */
KMC_BIT_KVMEM = 7, /* Use kvmalloc linux allocator */
KMC_BIT_SLAB = 8, /* Use Linux slab cache */
KMC_BIT_DEADLOCKED = 14, /* Deadlock detected */
@ -60,8 +58,6 @@ typedef enum kmem_cbrc {
} kmem_cbrc_t;
#define KMC_NODEBUG (1 << KMC_BIT_NODEBUG)
#define KMC_KMEM (1 << KMC_BIT_KMEM)
#define KMC_VMEM (1 << KMC_BIT_VMEM)
#define KMC_KVMEM (1 << KMC_BIT_KVMEM)
#define KMC_SLAB (1 << KMC_BIT_SLAB)
#define KMC_DEADLOCKED (1 << KMC_BIT_DEADLOCKED)

View File

@ -402,8 +402,6 @@ void procfs_list_add(procfs_list_t *procfs_list, void *p);
#define KM_NOSLEEP UMEM_DEFAULT
#define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */
#define KMC_NODEBUG UMC_NODEBUG
#define KMC_KMEM 0x0
#define KMC_VMEM 0x0
#define KMC_KVMEM 0x0
#define kmem_alloc(_s, _f) umem_alloc(_s, _f)
#define kmem_zalloc(_s, _f) umem_zalloc(_s, _f)

View File

@ -131,37 +131,6 @@ cutoff of 16K was determined to be optimal for architectures using 4K pages.
Default value: \fB16,384\fR
.RE
.sp
.ne 2
.na
\fBspl_kmem_cache_kmem_limit\fR (uint)
.ad
.RS 12n
Depending on the size of a cache object it may be backed by kmalloc()'d
or vmalloc()'d memory. This is because the size of the required allocation
greatly impacts the best way to allocate the memory.
.sp
When objects are small and only a small number of memory pages need to be
allocated, ideally just one, then kmalloc() is very efficient. However,
when allocating multiple pages with kmalloc() it gets increasingly expensive
because the pages must be physically contiguous.
.sp
For this reason we shift to vmalloc() for slabs of large objects which
which removes the need for contiguous pages. We cannot use vmalloc() in
all cases because there is significant locking overhead involved. This
function takes a single global lock over the entire virtual address range
which serializes all allocations. Using slightly different allocation
functions for small and large objects allows us to handle a wide range of
object sizes.
.sp
The \fBspl_kmem_cache_kmem_limit\fR value is used to determine this cutoff
size. One quarter the PAGE_SIZE is used as the default value because
\fBspl_kmem_cache_obj_per_slab\fR defaults to 16. This means that at
most we will need to allocate four contiguous pages.
.sp
Default value: \fBPAGE_SIZE/4\fR
.RE
.sp
.ne 2
.na

View File

@ -112,17 +112,6 @@ module_param(spl_kmem_cache_slab_limit, uint, 0644);
MODULE_PARM_DESC(spl_kmem_cache_slab_limit,
"Objects less than N bytes use the Linux slab");
/*
* This value defaults to a threshold designed to avoid allocations which
* have been deemed costly by the kernel.
*/
unsigned int spl_kmem_cache_kmem_limit =
((1 << (PAGE_ALLOC_COSTLY_ORDER - 1)) * PAGE_SIZE) /
SPL_KMEM_CACHE_OBJ_PER_SLAB;
module_param(spl_kmem_cache_kmem_limit, uint, 0644);
MODULE_PARM_DESC(spl_kmem_cache_kmem_limit,
"Objects less than N bytes use the kmalloc");
/*
* The number of threads available to allocate new slabs for caches. This
* should not need to be tuned but it is available for performance analysis.
@ -177,12 +166,7 @@ kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
gfp_t lflags = kmem_flags_convert(flags);
void *ptr;
if (skc->skc_flags & KMC_KMEM) {
ASSERT(ISP2(size));
ptr = (void *)__get_free_pages(lflags, get_order(size));
} else {
ptr = spl_vmalloc(size, lflags | __GFP_HIGHMEM);
}
ptr = spl_vmalloc(size, lflags | __GFP_HIGHMEM);
/* Resulting allocated memory will be page aligned */
ASSERT(IS_P2ALIGNED(ptr, PAGE_SIZE));
@ -205,12 +189,7 @@ kv_free(spl_kmem_cache_t *skc, void *ptr, int size)
if (current->reclaim_state)
current->reclaim_state->reclaimed_slab += size >> PAGE_SHIFT;
if (skc->skc_flags & KMC_KMEM) {
ASSERT(ISP2(size));
free_pages((unsigned long)ptr, get_order(size));
} else {
vfree(ptr);
}
vfree(ptr);
}
/*
@ -563,18 +542,6 @@ spl_slab_size(spl_kmem_cache_t *skc, uint32_t *objs, uint32_t *size)
max_size = (spl_kmem_cache_max_size * 1024 * 1024);
tgt_size = (spl_kmem_cache_obj_per_slab * obj_size + sks_size);
/*
* KMC_KMEM slabs are allocated by __get_free_pages() which
* rounds up to the nearest order. Knowing this the size
* should be rounded up to the next power of two with a hard
* maximum defined by the maximum allowed allocation order.
*/
if (skc->skc_flags & KMC_KMEM) {
max_size = SPL_MAX_ORDER_NR_PAGES * PAGE_SIZE;
tgt_size = MIN(max_size,
PAGE_SIZE * (1 << MAX(get_order(tgt_size) - 1, 1)));
}
if (tgt_size <= max_size) {
tgt_objs = (tgt_size - sks_size) / obj_size;
} else {
@ -714,8 +681,6 @@ spl_magazine_destroy(spl_kmem_cache_t *skc)
* priv cache private data for ctor/dtor/reclaim
* vmp unused must be NULL
* flags
* KMC_KMEM Force SPL kmem backed cache
* KMC_VMEM Force SPL vmem backed cache
* KMC_KVMEM Force kvmem backed SPL cache
* KMC_SLAB Force Linux slab backed cache
* KMC_NODEBUG Disable debugging (unsupported)
@ -801,7 +766,7 @@ spl_kmem_cache_create(char *name, size_t size, size_t align,
* linuxslab) then select a cache type based on the object size
* and default tunables.
*/
if (!(skc->skc_flags & (KMC_KMEM | KMC_VMEM | KMC_SLAB | KMC_KVMEM))) {
if (!(skc->skc_flags & (KMC_SLAB | KMC_KVMEM))) {
if (spl_kmem_cache_slab_limit &&
size <= (size_t)spl_kmem_cache_slab_limit) {
/*
@ -809,13 +774,6 @@ spl_kmem_cache_create(char *name, size_t size, size_t align,
* use the Linux slab for better space-efficiency.
*/
skc->skc_flags |= KMC_SLAB;
} else if (spl_obj_size(skc) <= spl_kmem_cache_kmem_limit) {
/*
* Small objects, less than spl_kmem_cache_kmem_limit
* per object should use kmem because their slabs are
* small.
*/
skc->skc_flags |= KMC_KMEM;
} else {
/*
* All other objects are considered large and are
@ -828,7 +786,7 @@ spl_kmem_cache_create(char *name, size_t size, size_t align,
/*
* Given the type of slab allocate the required resources.
*/
if (skc->skc_flags & (KMC_KMEM | KMC_VMEM | KMC_KVMEM)) {
if (skc->skc_flags & KMC_KVMEM) {
rc = spl_slab_size(skc,
&skc->skc_slab_objs, &skc->skc_slab_size);
if (rc)
@ -905,7 +863,7 @@ spl_kmem_cache_destroy(spl_kmem_cache_t *skc)
taskqid_t id;
ASSERT(skc->skc_magic == SKC_MAGIC);
ASSERT(skc->skc_flags & (KMC_KMEM | KMC_VMEM | KMC_KVMEM | KMC_SLAB));
ASSERT(skc->skc_flags & (KMC_KVMEM | KMC_SLAB));
down_write(&spl_kmem_cache_sem);
list_del_init(&skc->skc_list);
@ -927,7 +885,7 @@ spl_kmem_cache_destroy(spl_kmem_cache_t *skc)
*/
wait_event(wq, atomic_read(&skc->skc_ref) == 0);
if (skc->skc_flags & (KMC_KMEM | KMC_VMEM | KMC_KVMEM)) {
if (skc->skc_flags & KMC_KVMEM) {
spl_magazine_destroy(skc);
spl_slab_reclaim(skc);
} else {
@ -1079,21 +1037,13 @@ spl_cache_grow(spl_kmem_cache_t *skc, int flags, void **obj)
}
/*
* To reduce the overhead of context switch and improve NUMA locality,
* it tries to allocate a new slab in the current process context with
* KM_NOSLEEP flag. If it fails, it will launch a new taskq to do the
* allocation.
* Note: It would be nice to reduce the overhead of context switch
* and improve NUMA locality, by trying to allocate a new slab in the
* current process context with KM_NOSLEEP flag.
*
* However, this can't be applied to KVM_VMEM due to a bug that
* However, this can't be applied to vmem/kvmem due to a bug that
* spl_vmalloc() doesn't honor gfp flags in page table allocation.
*/
if (!(skc->skc_flags & KMC_VMEM) && !(skc->skc_flags & KMC_KVMEM)) {
rc = __spl_cache_grow(skc, flags | KM_NOSLEEP);
if (rc == 0) {
wake_up_all(&skc->skc_waitq);
return (0);
}
}
/*
* This is handled by dispatching a work request to the global work

View File

@ -631,60 +631,6 @@ static struct ctl_table spl_kmem_table[] = {
.proc_handler = &proc_doulongvec_minmax,
},
#endif /* DEBUG_KMEM */
{
.procname = "slab_kmem_total",
.data = (void *)(KMC_KMEM | KMC_TOTAL),
.maxlen = sizeof (unsigned long),
.extra1 = &table_min,
.extra2 = &table_max,
.mode = 0444,
.proc_handler = &proc_doslab,
},
{
.procname = "slab_kmem_alloc",
.data = (void *)(KMC_KMEM | KMC_ALLOC),
.maxlen = sizeof (unsigned long),
.extra1 = &table_min,
.extra2 = &table_max,
.mode = 0444,
.proc_handler = &proc_doslab,
},
{
.procname = "slab_kmem_max",
.data = (void *)(KMC_KMEM | KMC_MAX),
.maxlen = sizeof (unsigned long),
.extra1 = &table_min,
.extra2 = &table_max,
.mode = 0444,
.proc_handler = &proc_doslab,
},
{
.procname = "slab_vmem_total",
.data = (void *)(KMC_VMEM | KMC_TOTAL),
.maxlen = sizeof (unsigned long),
.extra1 = &table_min,
.extra2 = &table_max,
.mode = 0444,
.proc_handler = &proc_doslab,
},
{
.procname = "slab_vmem_alloc",
.data = (void *)(KMC_VMEM | KMC_ALLOC),
.maxlen = sizeof (unsigned long),
.extra1 = &table_min,
.extra2 = &table_max,
.mode = 0444,
.proc_handler = &proc_doslab,
},
{
.procname = "slab_vmem_max",
.data = (void *)(KMC_VMEM | KMC_MAX),
.maxlen = sizeof (unsigned long),
.extra1 = &table_min,
.extra2 = &table_max,
.mode = 0444,
.proc_handler = &proc_doslab,
},
{
.procname = "slab_kvmem_total",
.data = (void *)(KMC_KVMEM | KMC_TOTAL),