mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
mm/slab: allow specifying free pointer offset when using constructor
When a slab cache has a constructor, the free pointer is placed after the object because certain fields must not be overwritten even after the object is freed. However, some fields that the constructor does not initialize can safely be overwritten after free. Allow specifying the free pointer offset within the object, reducing the overall object size when some fields can be reused for the free pointer. Adjust the document accordingly. Signed-off-by: Harry Yoo <harry.yoo@oracle.com> Link: https://patch.msgid.link/20260113061845.159790-3-harry.yoo@oracle.com Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
This commit is contained in:
parent
b85f369b81
commit
a13b68d79d
|
|
@ -299,24 +299,26 @@ struct kmem_cache_args {
|
|||
unsigned int usersize;
|
||||
/**
|
||||
* @freeptr_offset: Custom offset for the free pointer
|
||||
* in &SLAB_TYPESAFE_BY_RCU caches
|
||||
* in caches with &SLAB_TYPESAFE_BY_RCU or @ctor
|
||||
*
|
||||
* By default &SLAB_TYPESAFE_BY_RCU caches place the free pointer
|
||||
* outside of the object. This might cause the object to grow in size.
|
||||
* Cache creators that have a reason to avoid this can specify a custom
|
||||
* free pointer offset in their struct where the free pointer will be
|
||||
* placed.
|
||||
* By default, &SLAB_TYPESAFE_BY_RCU and @ctor caches place the free
|
||||
* pointer outside of the object. This might cause the object to grow
|
||||
* in size. Cache creators that have a reason to avoid this can specify
|
||||
* a custom free pointer offset in their data structure where the free
|
||||
* pointer will be placed.
|
||||
*
|
||||
* Note that placing the free pointer inside the object requires the
|
||||
* caller to ensure that no fields are invalidated that are required to
|
||||
* guard against object recycling (See &SLAB_TYPESAFE_BY_RCU for
|
||||
* details).
|
||||
* For caches with &SLAB_TYPESAFE_BY_RCU, the caller must ensure that
|
||||
* the free pointer does not overlay fields required to guard against
|
||||
* object recycling (See &SLAB_TYPESAFE_BY_RCU for details).
|
||||
*
|
||||
* For caches with @ctor, the caller must ensure that the free pointer
|
||||
* does not overlay fields initialized by the constructor.
|
||||
*
|
||||
* Currently, only caches with &SLAB_TYPESAFE_BY_RCU or @ctor
|
||||
* may specify @freeptr_offset.
|
||||
*
|
||||
* Using %0 as a value for @freeptr_offset is valid. If @freeptr_offset
|
||||
* is specified, %use_freeptr_offset must be set %true.
|
||||
*
|
||||
* Note that @ctor currently isn't supported with custom free pointers
|
||||
* as a @ctor requires an external free pointer.
|
||||
* is specified, @use_freeptr_offset must be set %true.
|
||||
*/
|
||||
unsigned int freeptr_offset;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ static struct kmem_cache *create_cache(const char *name,
|
|||
err = -EINVAL;
|
||||
if (args->use_freeptr_offset &&
|
||||
(args->freeptr_offset >= object_size ||
|
||||
!(flags & SLAB_TYPESAFE_BY_RCU) ||
|
||||
(!(flags & SLAB_TYPESAFE_BY_RCU) && !args->ctor) ||
|
||||
!IS_ALIGNED(args->freeptr_offset, __alignof__(freeptr_t))))
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -7998,7 +7998,8 @@ static int calculate_sizes(struct kmem_cache_args *args, struct kmem_cache *s)
|
|||
s->inuse = size;
|
||||
|
||||
if (((flags & SLAB_TYPESAFE_BY_RCU) && !args->use_freeptr_offset) ||
|
||||
(flags & SLAB_POISON) || s->ctor ||
|
||||
(flags & SLAB_POISON) ||
|
||||
(s->ctor && !args->use_freeptr_offset) ||
|
||||
((flags & SLAB_RED_ZONE) &&
|
||||
(s->object_size < sizeof(void *) || slub_debug_orig_size(s)))) {
|
||||
/*
|
||||
|
|
@ -8019,7 +8020,8 @@ static int calculate_sizes(struct kmem_cache_args *args, struct kmem_cache *s)
|
|||
*/
|
||||
s->offset = size;
|
||||
size += sizeof(void *);
|
||||
} else if ((flags & SLAB_TYPESAFE_BY_RCU) && args->use_freeptr_offset) {
|
||||
} else if (((flags & SLAB_TYPESAFE_BY_RCU) || s->ctor) &&
|
||||
args->use_freeptr_offset) {
|
||||
s->offset = args->freeptr_offset;
|
||||
} else {
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user