Skip to content

Commit

Permalink
Remove KMC_KMEM and KMC_VMEM
Browse files Browse the repository at this point in the history
`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 <[email protected]>
Reviewed-by: Ryan Moeller <[email protected]>
Signed-off-by: Matthew Ahrens <[email protected]>
Closes openzfs#10673
  • Loading branch information
ahrens authored Aug 17, 2020
1 parent 3df0c2f commit 994de7e
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 151 deletions.
4 changes: 0 additions & 4 deletions include/os/linux/spl/sys/kmem_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions include/sys/zfs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 0 additions & 31 deletions man/man5/spl-module-parameters.5
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
70 changes: 10 additions & 60 deletions module/os/linux/spl/spl-kmem-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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));
Expand All @@ -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);
}

/*
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -801,21 +766,14 @@ 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) {
/*
* Objects smaller than spl_kmem_cache_slab_limit can
* 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
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
54 changes: 0 additions & 54 deletions module/os/linux/spl/spl-proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down

0 comments on commit 994de7e

Please sign in to comment.