Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm: make should_failslab always available for fault injection

should_failslab() is a convenient function to hook into for directed
error injection into kmalloc(). However, it is only available if a
config flag is set.

The following BCC script, for example, fails kmalloc() calls after a
btrfs umount:

from bcc import BPF

prog = r"""
BPF_HASH(flag);

#include <linux/mm.h>

int kprobe__btrfs_close_devices(void *ctx) {
u64 key = 1;
flag.update(&key, &key);
return 0;
}

int kprobe__should_failslab(struct pt_regs *ctx) {
u64 key = 1;
u64 *res;
res = flag.lookup(&key);
if (res != 0) {
bpf_override_return(ctx, -ENOMEM);
}
return 0;
}
"""
b = BPF(text=prog)

while 1:
b.kprobe_poll()

This patch refactors the should_failslab implementation so that the
function is always available for error injection, independent of flags.

This change would be similar in nature to commit f5490d3ec921 ("block:
Add should_fail_bio() for bpf error injection").

Link: http://lkml.kernel.org/r/20180222020320.6944-1-hmclauchlan@fb.com
Signed-off-by: Howard McLauchlan <hmclauchlan@fb.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Josef Bacik <jbacik@fb.com>
Cc: Johannes Weiner <jweiner@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Howard McLauchlan and committed by
Linus Torvalds
4f6923fb 14298d36

+12 -3
+3 -2
include/linux/fault-inject.h
··· 64 64 65 65 struct kmem_cache; 66 66 67 + int should_failslab(struct kmem_cache *s, gfp_t gfpflags); 67 68 #ifdef CONFIG_FAILSLAB 68 - extern bool should_failslab(struct kmem_cache *s, gfp_t gfpflags); 69 + extern bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags); 69 70 #else 70 - static inline bool should_failslab(struct kmem_cache *s, gfp_t gfpflags) 71 + static inline bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags) 71 72 { 72 73 return false; 73 74 }
+1 -1
mm/failslab.c
··· 14 14 .cache_filter = false, 15 15 }; 16 16 17 - bool should_failslab(struct kmem_cache *s, gfp_t gfpflags) 17 + bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags) 18 18 { 19 19 /* No fault-injection for bootstrap cache */ 20 20 if (unlikely(s == kmem_cache))
+8
mm/slab_common.c
··· 1516 1516 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc_node); 1517 1517 EXPORT_TRACEPOINT_SYMBOL(kfree); 1518 1518 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_free); 1519 + 1520 + int should_failslab(struct kmem_cache *s, gfp_t gfpflags) 1521 + { 1522 + if (__should_failslab(s, gfpflags)) 1523 + return -ENOMEM; 1524 + return 0; 1525 + } 1526 + ALLOW_ERROR_INJECTION(should_failslab, ERRNO);