Skip to content

Commit ea4452d

Browse files
Qi Zhengakpm00
authored andcommitted
mm: fix unexpected changes to {failslab|fail_page_alloc}.attr
When we specify __GFP_NOWARN, we only expect that no warnings will be issued for current caller. But in the __should_failslab() and __should_fail_alloc_page(), the local GFP flags alter the global {failslab|fail_page_alloc}.attr, which is persistent and shared by all tasks. This is not what we expected, let's fix it. [[email protected]: unexport should_fail_ex()] Link: https://lkml.kernel.org/r/[email protected] Fixes: 3f913fc ("mm: fix missing handler for __GFP_NOWARN") Signed-off-by: Qi Zheng <[email protected]> Reported-by: Dmitry Vyukov <[email protected]> Reviewed-by: Akinobu Mita <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Cc: Akinobu Mita <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent de1ccfb commit ea4452d

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

include/linux/fault-inject.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ struct fault_attr {
2020
atomic_t space;
2121
unsigned long verbose;
2222
bool task_filter;
23-
bool no_warn;
2423
unsigned long stacktrace_depth;
2524
unsigned long require_start;
2625
unsigned long require_end;
@@ -32,6 +31,10 @@ struct fault_attr {
3231
struct dentry *dname;
3332
};
3433

34+
enum fault_flags {
35+
FAULT_NOWARN = 1 << 0,
36+
};
37+
3538
#define FAULT_ATTR_INITIALIZER { \
3639
.interval = 1, \
3740
.times = ATOMIC_INIT(1), \
@@ -40,11 +43,11 @@ struct fault_attr {
4043
.ratelimit_state = RATELIMIT_STATE_INIT_DISABLED, \
4144
.verbose = 2, \
4245
.dname = NULL, \
43-
.no_warn = false, \
4446
}
4547

4648
#define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER
4749
int setup_fault_attr(struct fault_attr *attr, char *str);
50+
bool should_fail_ex(struct fault_attr *attr, ssize_t size, int flags);
4851
bool should_fail(struct fault_attr *attr, ssize_t size);
4952

5053
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS

lib/fault-inject.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ EXPORT_SYMBOL_GPL(setup_fault_attr);
4141

4242
static void fail_dump(struct fault_attr *attr)
4343
{
44-
if (attr->no_warn)
45-
return;
46-
4744
if (attr->verbose > 0 && __ratelimit(&attr->ratelimit_state)) {
4845
printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n"
4946
"name %pd, interval %lu, probability %lu, "
@@ -103,7 +100,7 @@ static inline bool fail_stacktrace(struct fault_attr *attr)
103100
* http://www.nongnu.org/failmalloc/
104101
*/
105102

106-
bool should_fail(struct fault_attr *attr, ssize_t size)
103+
bool should_fail_ex(struct fault_attr *attr, ssize_t size, int flags)
107104
{
108105
if (in_task()) {
109106
unsigned int fail_nth = READ_ONCE(current->fail_nth);
@@ -146,13 +143,19 @@ bool should_fail(struct fault_attr *attr, ssize_t size)
146143
return false;
147144

148145
fail:
149-
fail_dump(attr);
146+
if (!(flags & FAULT_NOWARN))
147+
fail_dump(attr);
150148

151149
if (atomic_read(&attr->times) != -1)
152150
atomic_dec_not_zero(&attr->times);
153151

154152
return true;
155153
}
154+
155+
bool should_fail(struct fault_attr *attr, ssize_t size)
156+
{
157+
return should_fail_ex(attr, size, 0);
158+
}
156159
EXPORT_SYMBOL_GPL(should_fail);
157160

158161
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS

mm/failslab.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ static struct {
1616

1717
bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
1818
{
19+
int flags = 0;
20+
1921
/* No fault-injection for bootstrap cache */
2022
if (unlikely(s == kmem_cache))
2123
return false;
@@ -30,10 +32,16 @@ bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
3032
if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB))
3133
return false;
3234

35+
/*
36+
* In some cases, it expects to specify __GFP_NOWARN
37+
* to avoid printing any information(not just a warning),
38+
* thus avoiding deadlocks. See commit 6b9dbedbe349 for
39+
* details.
40+
*/
3341
if (gfpflags & __GFP_NOWARN)
34-
failslab.attr.no_warn = true;
42+
flags |= FAULT_NOWARN;
3543

36-
return should_fail(&failslab.attr, s->object_size);
44+
return should_fail_ex(&failslab.attr, s->object_size, flags);
3745
}
3846

3947
static int __init setup_failslab(char *str)

mm/page_alloc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,6 +3887,8 @@ __setup("fail_page_alloc=", setup_fail_page_alloc);
38873887

38883888
static bool __should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
38893889
{
3890+
int flags = 0;
3891+
38903892
if (order < fail_page_alloc.min_order)
38913893
return false;
38923894
if (gfp_mask & __GFP_NOFAIL)
@@ -3897,10 +3899,11 @@ static bool __should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
38973899
(gfp_mask & __GFP_DIRECT_RECLAIM))
38983900
return false;
38993901

3902+
/* See comment in __should_failslab() */
39003903
if (gfp_mask & __GFP_NOWARN)
3901-
fail_page_alloc.attr.no_warn = true;
3904+
flags |= FAULT_NOWARN;
39023905

3903-
return should_fail(&fail_page_alloc.attr, 1 << order);
3906+
return should_fail_ex(&fail_page_alloc.attr, 1 << order, flags);
39043907
}
39053908

39063909
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS

0 commit comments

Comments
 (0)