Skip to content

Commit 879fb3c

Browse files
braunertehcaster
authored andcommitted
slab: add struct kmem_cache_args
Currently we have multiple kmem_cache_create*() variants that take up to seven separate parameters with one of the functions having to grow an eigth parameter in the future to handle both usercopy and a custom freelist pointer. Add a struct kmem_cache_args structure and move less common parameters into it. Core parameters such as name, object size, and flags continue to be passed separately. Add a new function __kmem_cache_create_args() that takes a struct kmem_cache_args pointer and port do_kmem_cache_create_usercopy() over to it. In follow-up patches we will port the other kmem_cache_create*() variants over to it as well. Reviewed-by: Kees Cook <[email protected]> Reviewed-by: Jens Axboe <[email protected]> Reviewed-by: Mike Rapoport (Microsoft) <[email protected]> Reviewed-by: Vlastimil Babka <[email protected]> Signed-off-by: Christian Brauner <[email protected]> Reviewed-by: Roman Gushchin <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent 53d3d21 commit 879fb3c

File tree

2 files changed

+73
-16
lines changed

2 files changed

+73
-16
lines changed

include/linux/slab.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,28 @@ struct mem_cgroup;
240240
*/
241241
bool slab_is_available(void);
242242

243+
/**
244+
* struct kmem_cache_args - Less common arguments for kmem_cache_create()
245+
* @align: The required alignment for the objects.
246+
* @useroffset: Usercopy region offset
247+
* @usersize: Usercopy region size
248+
* @freeptr_offset: Custom offset for the free pointer in RCU caches
249+
* @use_freeptr_offset: Whether a @freeptr_offset is used
250+
* @ctor: A constructor for the objects.
251+
*/
252+
struct kmem_cache_args {
253+
unsigned int align;
254+
unsigned int useroffset;
255+
unsigned int usersize;
256+
unsigned int freeptr_offset;
257+
bool use_freeptr_offset;
258+
void (*ctor)(void *);
259+
};
260+
261+
struct kmem_cache *__kmem_cache_create_args(const char *name,
262+
unsigned int object_size,
263+
struct kmem_cache_args *args,
264+
slab_flags_t flags);
243265
struct kmem_cache *kmem_cache_create(const char *name, unsigned int size,
244266
unsigned int align, slab_flags_t flags,
245267
void (*ctor)(void *));

mm/slab_common.c

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,24 @@ static struct kmem_cache *create_cache(const char *name,
248248
return ERR_PTR(err);
249249
}
250250

251-
static struct kmem_cache *
252-
do_kmem_cache_create_usercopy(const char *name,
253-
unsigned int size, unsigned int freeptr_offset,
254-
unsigned int align, slab_flags_t flags,
255-
unsigned int useroffset, unsigned int usersize,
256-
void (*ctor)(void *))
251+
/**
252+
* __kmem_cache_create_args - Create a kmem cache
253+
* @name: A string which is used in /proc/slabinfo to identify this cache.
254+
* @object_size: The size of objects to be created in this cache.
255+
* @args: Arguments for the cache creation (see struct kmem_cache_args).
256+
* @flags: See %SLAB_* flags for an explanation of individual @flags.
257+
*
258+
* Cannot be called within a interrupt, but can be interrupted.
259+
*
260+
* Return: a pointer to the cache on success, NULL on failure.
261+
*/
262+
struct kmem_cache *__kmem_cache_create_args(const char *name,
263+
unsigned int object_size,
264+
struct kmem_cache_args *args,
265+
slab_flags_t flags)
257266
{
258267
struct kmem_cache *s = NULL;
268+
unsigned int freeptr_offset = UINT_MAX;
259269
const char *cache_name;
260270
int err;
261271

@@ -275,7 +285,7 @@ do_kmem_cache_create_usercopy(const char *name,
275285

276286
mutex_lock(&slab_mutex);
277287

278-
err = kmem_cache_sanity_check(name, size);
288+
err = kmem_cache_sanity_check(name, object_size);
279289
if (err) {
280290
goto out_unlock;
281291
}
@@ -296,12 +306,14 @@ do_kmem_cache_create_usercopy(const char *name,
296306

297307
/* Fail closed on bad usersize of useroffset values. */
298308
if (!IS_ENABLED(CONFIG_HARDENED_USERCOPY) ||
299-
WARN_ON(!usersize && useroffset) ||
300-
WARN_ON(size < usersize || size - usersize < useroffset))
301-
usersize = useroffset = 0;
302-
303-
if (!usersize)
304-
s = __kmem_cache_alias(name, size, align, flags, ctor);
309+
WARN_ON(!args->usersize && args->useroffset) ||
310+
WARN_ON(object_size < args->usersize ||
311+
object_size - args->usersize < args->useroffset))
312+
args->usersize = args->useroffset = 0;
313+
314+
if (!args->usersize)
315+
s = __kmem_cache_alias(name, object_size, args->align, flags,
316+
args->ctor);
305317
if (s)
306318
goto out_unlock;
307319

@@ -311,9 +323,11 @@ do_kmem_cache_create_usercopy(const char *name,
311323
goto out_unlock;
312324
}
313325

314-
s = create_cache(cache_name, size, freeptr_offset,
315-
calculate_alignment(flags, align, size),
316-
flags, useroffset, usersize, ctor);
326+
if (args->use_freeptr_offset)
327+
freeptr_offset = args->freeptr_offset;
328+
s = create_cache(cache_name, object_size, freeptr_offset,
329+
calculate_alignment(flags, args->align, object_size),
330+
flags, args->useroffset, args->usersize, args->ctor);
317331
if (IS_ERR(s)) {
318332
err = PTR_ERR(s);
319333
kfree_const(cache_name);
@@ -335,6 +349,27 @@ do_kmem_cache_create_usercopy(const char *name,
335349
}
336350
return s;
337351
}
352+
EXPORT_SYMBOL(__kmem_cache_create_args);
353+
354+
static struct kmem_cache *
355+
do_kmem_cache_create_usercopy(const char *name,
356+
unsigned int size, unsigned int freeptr_offset,
357+
unsigned int align, slab_flags_t flags,
358+
unsigned int useroffset, unsigned int usersize,
359+
void (*ctor)(void *))
360+
{
361+
struct kmem_cache_args kmem_args = {
362+
.align = align,
363+
.use_freeptr_offset = freeptr_offset != UINT_MAX,
364+
.freeptr_offset = freeptr_offset,
365+
.useroffset = useroffset,
366+
.usersize = usersize,
367+
.ctor = ctor,
368+
};
369+
370+
return __kmem_cache_create_args(name, size, &kmem_args, flags);
371+
}
372+
338373

339374
/**
340375
* kmem_cache_create_usercopy - Create a cache with a region suitable

0 commit comments

Comments
 (0)