xref: /openbmc/linux/mm/failslab.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2773ff60eSAkinobu Mita #include <linux/fault-inject.h>
34c13dd3bSDmitry Monakhov #include <linux/slab.h>
4fab9963aSJesper Dangaard Brouer #include <linux/mm.h>
5fab9963aSJesper Dangaard Brouer #include "slab.h"
6773ff60eSAkinobu Mita 
7773ff60eSAkinobu Mita static struct {
8773ff60eSAkinobu Mita 	struct fault_attr attr;
971baba4bSMel Gorman 	bool ignore_gfp_reclaim;
10621a5f7aSViresh Kumar 	bool cache_filter;
11773ff60eSAkinobu Mita } failslab = {
12773ff60eSAkinobu Mita 	.attr = FAULT_ATTR_INITIALIZER,
1371baba4bSMel Gorman 	.ignore_gfp_reclaim = true,
14621a5f7aSViresh Kumar 	.cache_filter = false,
15773ff60eSAkinobu Mita };
16773ff60eSAkinobu Mita 
__should_failslab(struct kmem_cache * s,gfp_t gfpflags)174f6923fbSHoward McLauchlan bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
18773ff60eSAkinobu Mita {
19*ea4452deSQi Zheng 	int flags = 0;
20*ea4452deSQi Zheng 
21fab9963aSJesper Dangaard Brouer 	/* No fault-injection for bootstrap cache */
22fab9963aSJesper Dangaard Brouer 	if (unlikely(s == kmem_cache))
23fab9963aSJesper Dangaard Brouer 		return false;
24fab9963aSJesper Dangaard Brouer 
25773ff60eSAkinobu Mita 	if (gfpflags & __GFP_NOFAIL)
26773ff60eSAkinobu Mita 		return false;
27773ff60eSAkinobu Mita 
28a9659476SNicolas Boichat 	if (failslab.ignore_gfp_reclaim &&
29a9659476SNicolas Boichat 			(gfpflags & __GFP_DIRECT_RECLAIM))
30773ff60eSAkinobu Mita 		return false;
31773ff60eSAkinobu Mita 
32fab9963aSJesper Dangaard Brouer 	if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB))
334c13dd3bSDmitry Monakhov 		return false;
344c13dd3bSDmitry Monakhov 
35*ea4452deSQi Zheng 	/*
36*ea4452deSQi Zheng 	 * In some cases, it expects to specify __GFP_NOWARN
37*ea4452deSQi Zheng 	 * to avoid printing any information(not just a warning),
38*ea4452deSQi Zheng 	 * thus avoiding deadlocks. See commit 6b9dbedbe349 for
39*ea4452deSQi Zheng 	 * details.
40*ea4452deSQi Zheng 	 */
413f913fc5SQi Zheng 	if (gfpflags & __GFP_NOWARN)
42*ea4452deSQi Zheng 		flags |= FAULT_NOWARN;
433f913fc5SQi Zheng 
44*ea4452deSQi Zheng 	return should_fail_ex(&failslab.attr, s->object_size, flags);
45773ff60eSAkinobu Mita }
46773ff60eSAkinobu Mita 
setup_failslab(char * str)47773ff60eSAkinobu Mita static int __init setup_failslab(char *str)
48773ff60eSAkinobu Mita {
49773ff60eSAkinobu Mita 	return setup_fault_attr(&failslab.attr, str);
50773ff60eSAkinobu Mita }
51773ff60eSAkinobu Mita __setup("failslab=", setup_failslab);
52773ff60eSAkinobu Mita 
53773ff60eSAkinobu Mita #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
failslab_debugfs_init(void)54773ff60eSAkinobu Mita static int __init failslab_debugfs_init(void)
55773ff60eSAkinobu Mita {
56dd48c085SAkinobu Mita 	struct dentry *dir;
570825a6f9SJoe Perches 	umode_t mode = S_IFREG | 0600;
58773ff60eSAkinobu Mita 
59dd48c085SAkinobu Mita 	dir = fault_create_debugfs_attr("failslab", NULL, &failslab.attr);
60dd48c085SAkinobu Mita 	if (IS_ERR(dir))
61dd48c085SAkinobu Mita 		return PTR_ERR(dir);
62773ff60eSAkinobu Mita 
63d9f7979cSGreg Kroah-Hartman 	debugfs_create_bool("ignore-gfp-wait", mode, dir,
64d9f7979cSGreg Kroah-Hartman 			    &failslab.ignore_gfp_reclaim);
65d9f7979cSGreg Kroah-Hartman 	debugfs_create_bool("cache-filter", mode, dir,
66d9f7979cSGreg Kroah-Hartman 			    &failslab.cache_filter);
67773ff60eSAkinobu Mita 
68810f09b8SAkinobu Mita 	return 0;
69773ff60eSAkinobu Mita }
70773ff60eSAkinobu Mita 
71773ff60eSAkinobu Mita late_initcall(failslab_debugfs_init);
72773ff60eSAkinobu Mita 
73773ff60eSAkinobu Mita #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
74