Skip to content

Commit a7526fe

Browse files
tehcasterakpm00
authored andcommitted
mm, slab: put should_failslab() back behind CONFIG_SHOULD_FAILSLAB
Patch series "revert unconditional slab and page allocator fault injection calls". These two patches largely revert commits that added function call overhead into slab and page allocation hotpaths and that cannot be currently disabled even though related CONFIG_ options do exist. A much more involved solution that can keep the callsites always existing but hidden behind a static key if unused, is possible [1] and can be pursued by anyone who believes it's necessary. Meanwhile the fact the should_failslab() error injection is already not functional on kernels built with current gcc without anyone noticing [2], and lukewarm response to [1] suggests the need is not there. I believe it will be more fair to have the state after this series as a baseline for possible further optimisation, instead of the unconditional overhead. For example a possible compromise for anyone who's fine with an empty function call overhead but not the full CONFIG_FAILSLAB / CONFIG_FAIL_PAGE_ALLOC overhead is to reuse patch 1 from [1] but insert a static key check only inside should_failslab() and should_fail_alloc_page() before performing the more expensive checks. [1] https://lore.kernel.org/all/[email protected]/#t [2] bpftrace/bpftrace#3258 This patch (of 2): This mostly reverts commit 4f6923f ("mm: make should_failslab always available for fault injection"). The commit made should_failslab() a noinline function that's always called from the slab allocation hotpath, even if it's empty because CONFIG_SHOULD_FAILSLAB is not enabled, and there is no option to disable that call. This is visible in profiles and the function call overhead can be noticeable especially with cpu mitigations. Meanwhile the bpftrace program example in the commit silently does not work without CONFIG_SHOULD_FAILSLAB anyway with a recent gcc, because the empty function gets a .constprop clone that is actually being called (uselessly) from the slab hotpath, while the error injection is hooked to the original function that's not being called at all [1]. Thus put the whole should_failslab() function back behind CONFIG_SHOULD_FAILSLAB. It's not a complete revert of 4f6923f - the int return type that returns -ENOMEM on failure is preserved, as well ALLOW_ERROR_INJECTION annotation. The BTF_ID() record that was meanwhile added is also guarded by CONFIG_SHOULD_FAILSLAB. [1] bpftrace/bpftrace#3258 Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Vlastimil Babka <[email protected]> Cc: Akinobu Mita <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Christoph Lameter <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: David Rientjes <[email protected]> Cc: Eduard Zingerman <[email protected]> Cc: Hao Luo <[email protected]> Cc: Hyeonggon Yoo <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Fastabend <[email protected]> Cc: KP Singh <[email protected]> Cc: Martin KaFai Lau <[email protected]> Cc: Mateusz Guzik <[email protected]> Cc: Roman Gushchin <[email protected]> Cc: Song Liu <[email protected]> Cc: Stanislav Fomichev <[email protected]> Cc: Yonghong Song <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7b7aca6 commit a7526fe

File tree

4 files changed

+12
-17
lines changed

4 files changed

+12
-17
lines changed

include/linux/fault-inject.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,10 @@ static inline bool __should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
102102
}
103103
#endif /* CONFIG_FAIL_PAGE_ALLOC */
104104

105-
int should_failslab(struct kmem_cache *s, gfp_t gfpflags);
106105
#ifdef CONFIG_FAILSLAB
107-
extern bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags);
106+
int should_failslab(struct kmem_cache *s, gfp_t gfpflags);
108107
#else
109-
static inline bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
108+
static inline int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
110109
{
111110
return false;
112111
}

kernel/bpf/verifier.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21123,7 +21123,9 @@ BTF_SET_START(btf_non_sleepable_error_inject)
2112321123
*/
2112421124
BTF_ID(func, __filemap_add_folio)
2112521125
BTF_ID(func, should_fail_alloc_page)
21126+
#ifdef CONFIG_FAILSLAB
2112621127
BTF_ID(func, should_failslab)
21128+
#endif
2112721129
BTF_SET_END(btf_non_sleepable_error_inject)
2112821130

2112921131
static int check_non_sleepable_error_inject(u32 btf_id)

mm/failslab.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/fault-inject.h>
3+
#include <linux/error-injection.h>
34
#include <linux/slab.h>
45
#include <linux/mm.h>
56
#include "slab.h"
@@ -14,23 +15,23 @@ static struct {
1415
.cache_filter = false,
1516
};
1617

17-
bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
18+
int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
1819
{
1920
int flags = 0;
2021

2122
/* No fault-injection for bootstrap cache */
2223
if (unlikely(s == kmem_cache))
23-
return false;
24+
return 0;
2425

2526
if (gfpflags & __GFP_NOFAIL)
26-
return false;
27+
return 0;
2728

2829
if (failslab.ignore_gfp_reclaim &&
2930
(gfpflags & __GFP_DIRECT_RECLAIM))
30-
return false;
31+
return 0;
3132

3233
if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB))
33-
return false;
34+
return 0;
3435

3536
/*
3637
* In some cases, it expects to specify __GFP_NOWARN
@@ -41,8 +42,9 @@ bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
4142
if (gfpflags & __GFP_NOWARN)
4243
flags |= FAULT_NOWARN;
4344

44-
return should_fail_ex(&failslab.attr, s->object_size, flags);
45+
return should_fail_ex(&failslab.attr, s->object_size, flags) ? -ENOMEM : 0;
4546
}
47+
ALLOW_ERROR_INJECTION(should_failslab, ERRNO);
4648

4749
static int __init setup_failslab(char *str)
4850
{

mm/slub.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3892,14 +3892,6 @@ static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s,
38923892
0, sizeof(void *));
38933893
}
38943894

3895-
noinline int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
3896-
{
3897-
if (__should_failslab(s, gfpflags))
3898-
return -ENOMEM;
3899-
return 0;
3900-
}
3901-
ALLOW_ERROR_INJECTION(should_failslab, ERRNO);
3902-
39033895
static __fastpath_inline
39043896
struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags)
39053897
{

0 commit comments

Comments
 (0)