Skip to content

Commit 44e0ebe

Browse files
author
Vlastimil Babka (SUSE)
committed
Merge branch 'slab/for-7.1/misc' into slab/for-next
Merge misc slab changes that are not related to sheaves. Various improvements for sysfs, debugging and testing.
2 parents 5127483 + 92af129 commit 44e0ebe

4 files changed

Lines changed: 102 additions & 16 deletions

File tree

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24354,6 +24354,7 @@ F: Documentation/admin-guide/mm/slab.rst
2435424354
F: Documentation/mm/slab.rst
2435524355
F: include/linux/mempool.h
2435624356
F: include/linux/slab.h
24357+
F: lib/tests/slub_kunit.c
2435724358
F: mm/failslab.c
2435824359
F: mm/mempool.c
2435924360
F: mm/slab.h

lib/tests/slub_kunit.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/kernel.h>
88
#include <linux/rcupdate.h>
99
#include <linux/delay.h>
10+
#include <linux/perf_event.h>
1011
#include "../mm/slab.h"
1112

1213
static struct kunit_resource resource;
@@ -291,6 +292,94 @@ static void test_krealloc_redzone_zeroing(struct kunit *test)
291292
kmem_cache_destroy(s);
292293
}
293294

295+
#ifdef CONFIG_PERF_EVENTS
296+
#define NR_ITERATIONS 1000
297+
#define NR_OBJECTS 1000
298+
static void *objects[NR_OBJECTS];
299+
300+
struct test_nolock_context {
301+
struct kunit *test;
302+
int callback_count;
303+
int alloc_ok;
304+
int alloc_fail;
305+
struct perf_event *event;
306+
};
307+
308+
static struct perf_event_attr hw_attr = {
309+
.type = PERF_TYPE_HARDWARE,
310+
.config = PERF_COUNT_HW_CPU_CYCLES,
311+
.size = sizeof(struct perf_event_attr),
312+
.pinned = 1,
313+
.disabled = 1,
314+
.freq = 1,
315+
.sample_freq = 100000,
316+
};
317+
318+
static void overflow_handler_test_kmalloc_kfree_nolock(struct perf_event *event,
319+
struct perf_sample_data *data,
320+
struct pt_regs *regs)
321+
{
322+
void *objp;
323+
gfp_t gfp;
324+
struct test_nolock_context *ctx = event->overflow_handler_context;
325+
326+
/* __GFP_ACCOUNT to test kmalloc_nolock() in alloc_slab_obj_exts() */
327+
gfp = (ctx->callback_count % 2) ? 0 : __GFP_ACCOUNT;
328+
objp = kmalloc_nolock(64, gfp, NUMA_NO_NODE);
329+
330+
if (objp)
331+
ctx->alloc_ok++;
332+
else
333+
ctx->alloc_fail++;
334+
335+
kfree_nolock(objp);
336+
ctx->callback_count++;
337+
}
338+
339+
static void test_kmalloc_kfree_nolock(struct kunit *test)
340+
{
341+
int i, j;
342+
struct test_nolock_context ctx = { .test = test };
343+
struct perf_event *event;
344+
bool alloc_fail = false;
345+
346+
event = perf_event_create_kernel_counter(&hw_attr, -1, current,
347+
overflow_handler_test_kmalloc_kfree_nolock,
348+
&ctx);
349+
if (IS_ERR(event))
350+
kunit_skip(test, "Failed to create perf event");
351+
ctx.event = event;
352+
perf_event_enable(ctx.event);
353+
for (i = 0; i < NR_ITERATIONS; i++) {
354+
for (j = 0; j < NR_OBJECTS; j++) {
355+
gfp_t gfp = (i % 2) ? GFP_KERNEL : GFP_KERNEL_ACCOUNT;
356+
357+
objects[j] = kmalloc(64, gfp);
358+
if (!objects[j]) {
359+
j--;
360+
while (j >= 0)
361+
kfree(objects[j--]);
362+
alloc_fail = true;
363+
goto cleanup;
364+
}
365+
}
366+
for (j = 0; j < NR_OBJECTS; j++)
367+
kfree(objects[j]);
368+
}
369+
370+
cleanup:
371+
perf_event_disable(ctx.event);
372+
perf_event_release_kernel(ctx.event);
373+
374+
kunit_info(test, "callback_count: %d, alloc_ok: %d, alloc_fail: %d\n",
375+
ctx.callback_count, ctx.alloc_ok, ctx.alloc_fail);
376+
377+
if (alloc_fail)
378+
kunit_skip(test, "Allocation failed");
379+
KUNIT_EXPECT_EQ(test, 0, slab_errors);
380+
}
381+
#endif
382+
294383
static int test_init(struct kunit *test)
295384
{
296385
slab_errors = 0;
@@ -315,6 +404,9 @@ static struct kunit_case test_cases[] = {
315404
KUNIT_CASE(test_kfree_rcu_wq_destroy),
316405
KUNIT_CASE(test_leak_destroy),
317406
KUNIT_CASE(test_krealloc_redzone_zeroing),
407+
#ifdef CONFIG_PERF_EVENTS
408+
KUNIT_CASE_SLOW(test_kmalloc_kfree_nolock),
409+
#endif
318410
{}
319411
};
320412

mm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ config SLUB
172172
config KVFREE_RCU_BATCHED
173173
def_bool y
174174
depends on !SLUB_TINY && !TINY_RCU
175+
depends on !RCU_STRICT_GRACE_PERIOD
175176

176177
config SLUB_TINY
177178
bool "Configure for minimal memory footprint"

mm/slub.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8975,7 +8975,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
89758975
return len;
89768976
}
89778977

8978-
#define to_slab_attr(n) container_of(n, struct slab_attribute, attr)
8978+
#define to_slab_attr(n) container_of_const(n, struct slab_attribute, attr)
89798979
#define to_slab(n) container_of(n, struct kmem_cache, kobj)
89808980

89818981
struct slab_attribute {
@@ -8985,10 +8985,10 @@ struct slab_attribute {
89858985
};
89868986

89878987
#define SLAB_ATTR_RO(_name) \
8988-
static struct slab_attribute _name##_attr = __ATTR_RO_MODE(_name, 0400)
8988+
static const struct slab_attribute _name##_attr = __ATTR_RO_MODE(_name, 0400)
89898989

89908990
#define SLAB_ATTR(_name) \
8991-
static struct slab_attribute _name##_attr = __ATTR_RW_MODE(_name, 0600)
8991+
static const struct slab_attribute _name##_attr = __ATTR_RW_MODE(_name, 0600)
89928992

89938993
static ssize_t slab_size_show(struct kmem_cache *s, char *buf)
89948994
{
@@ -9382,7 +9382,7 @@ static ssize_t skip_kfence_store(struct kmem_cache *s,
93829382
SLAB_ATTR(skip_kfence);
93839383
#endif
93849384

9385-
static struct attribute *slab_attrs[] = {
9385+
static const struct attribute *const slab_attrs[] = {
93869386
&slab_size_attr.attr,
93879387
&object_size_attr.attr,
93889388
&objs_per_slab_attr.attr,
@@ -9459,15 +9459,13 @@ static struct attribute *slab_attrs[] = {
94599459
NULL
94609460
};
94619461

9462-
static const struct attribute_group slab_attr_group = {
9463-
.attrs = slab_attrs,
9464-
};
9462+
ATTRIBUTE_GROUPS(slab);
94659463

94669464
static ssize_t slab_attr_show(struct kobject *kobj,
94679465
struct attribute *attr,
94689466
char *buf)
94699467
{
9470-
struct slab_attribute *attribute;
9468+
const struct slab_attribute *attribute;
94719469
struct kmem_cache *s;
94729470

94739471
attribute = to_slab_attr(attr);
@@ -9483,7 +9481,7 @@ static ssize_t slab_attr_store(struct kobject *kobj,
94839481
struct attribute *attr,
94849482
const char *buf, size_t len)
94859483
{
9486-
struct slab_attribute *attribute;
9484+
const struct slab_attribute *attribute;
94879485
struct kmem_cache *s;
94889486

94899487
attribute = to_slab_attr(attr);
@@ -9508,6 +9506,7 @@ static const struct sysfs_ops slab_sysfs_ops = {
95089506
static const struct kobj_type slab_ktype = {
95099507
.sysfs_ops = &slab_sysfs_ops,
95109508
.release = kmem_cache_release,
9509+
.default_groups = slab_groups,
95119510
};
95129511

95139512
static struct kset *slab_kset;
@@ -9595,10 +9594,6 @@ static int sysfs_slab_add(struct kmem_cache *s)
95959594
if (err)
95969595
goto out;
95979596

9598-
err = sysfs_create_group(&s->kobj, &slab_attr_group);
9599-
if (err)
9600-
goto out_del_kobj;
9601-
96029597
if (!unmergeable) {
96039598
/* Setup first alias */
96049599
sysfs_slab_alias(s, s->name);
@@ -9607,9 +9602,6 @@ static int sysfs_slab_add(struct kmem_cache *s)
96079602
if (!unmergeable)
96089603
kfree(name);
96099604
return err;
9610-
out_del_kobj:
9611-
kobject_del(&s->kobj);
9612-
goto out;
96139605
}
96149606

96159607
void sysfs_slab_unlink(struct kmem_cache *s)

0 commit comments

Comments
 (0)