Skip to content

Commit 282acb4

Browse files
labbotttorvalds
authored andcommitted
slub: drop lock at the end of free_debug_processing
This series takes the suggestion of Christoph Lameter and only focuses on optimizing the slow path where the debug processing runs. The two main optimizations in this series are letting the consistency checks be skipped and relaxing the cmpxchg restrictions when we are not doing consistency checks. With hackbench -g 20 -l 1000 averaged over 100 runs: Before slub_debug=P mean 15.607 variance .086 stdev .294 After slub_debug=P mean 10.836 variance .155 stdev .394 This still isn't as fast as what is in grsecurity unfortunately so there's still work to be done. Profiling ___slab_alloc shows that 25-50% of time is spent in deactivate_slab. I haven't looked too closely to see if this is something that can be optimized. My plan for now is to focus on getting all of this merged (if appropriate) before digging in to another task. This patch (of 4): Currently, free_debug_processing has a comment "Keep node_lock to preserve integrity until the object is actually freed". In actuallity, the lock is dropped immediately in __slab_free. Rather than wait until __slab_free and potentially throw off the unlikely marking, just drop the lock in __slab_free. This also lets free_debug_processing take its own copy of the spinlock flags rather than trying to share the ones from __slab_free. Since there is no use for the node afterwards, change the return type of free_debug_processing to return an int like alloc_debug_processing. Credit to Mathias Krause for the original work which inspired this series [akpm@linux-foundation.org: fix build] Signed-off-by: Laura Abbott <labbott@fedoraproject.org> Acked-by: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Cc: Joonsoo Kim <js1304@gmail.com> Cc: Kees Cook <keescook@chromium.org> Cc: Mathias Krause <minipli@googlemail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent f68f8dd commit 282acb4

File tree

1 file changed

+11
-14
lines changed

1 file changed

+11
-14
lines changed

mm/slub.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,16 +1044,17 @@ static noinline int alloc_debug_processing(struct kmem_cache *s,
10441044
}
10451045

10461046
/* Supports checking bulk free of a constructed freelist */
1047-
static noinline struct kmem_cache_node *free_debug_processing(
1047+
static noinline int free_debug_processing(
10481048
struct kmem_cache *s, struct page *page,
10491049
void *head, void *tail, int bulk_cnt,
1050-
unsigned long addr, unsigned long *flags)
1050+
unsigned long addr)
10511051
{
10521052
struct kmem_cache_node *n = get_node(s, page_to_nid(page));
10531053
void *object = head;
10541054
int cnt = 0;
1055+
unsigned long uninitialized_var(flags);
10551056

1056-
spin_lock_irqsave(&n->list_lock, *flags);
1057+
spin_lock_irqsave(&n->list_lock, flags);
10571058
slab_lock(page);
10581059

10591060
if (!check_slab(s, page))
@@ -1106,17 +1107,14 @@ static noinline struct kmem_cache_node *free_debug_processing(
11061107
bulk_cnt, cnt);
11071108

11081109
slab_unlock(page);
1109-
/*
1110-
* Keep node_lock to preserve integrity
1111-
* until the object is actually freed
1112-
*/
1113-
return n;
1110+
spin_unlock_irqrestore(&n->list_lock, flags);
1111+
return 1;
11141112

11151113
fail:
11161114
slab_unlock(page);
1117-
spin_unlock_irqrestore(&n->list_lock, *flags);
1115+
spin_unlock_irqrestore(&n->list_lock, flags);
11181116
slab_fix(s, "Object at 0x%p not freed", object);
1119-
return NULL;
1117+
return 0;
11201118
}
11211119

11221120
static int __init setup_slub_debug(char *str)
@@ -1207,10 +1205,10 @@ static inline void setup_object_debug(struct kmem_cache *s,
12071205
static inline int alloc_debug_processing(struct kmem_cache *s,
12081206
struct page *page, void *object, unsigned long addr) { return 0; }
12091207

1210-
static inline struct kmem_cache_node *free_debug_processing(
1208+
static inline int free_debug_processing(
12111209
struct kmem_cache *s, struct page *page,
12121210
void *head, void *tail, int bulk_cnt,
1213-
unsigned long addr, unsigned long *flags) { return NULL; }
1211+
unsigned long addr) { return 0; }
12141212

12151213
static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
12161214
{ return 1; }
@@ -2588,8 +2586,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
25882586
stat(s, FREE_SLOWPATH);
25892587

25902588
if (kmem_cache_debug(s) &&
2591-
!(n = free_debug_processing(s, page, head, tail, cnt,
2592-
addr, &flags)))
2589+
!free_debug_processing(s, page, head, tail, cnt, addr))
25932590
return;
25942591

25952592
do {

0 commit comments

Comments
 (0)