| 1 | |
| 2 | #include <linux/fault-inject.h>
|
| 3 | #include <linux/error-injection.h>
|
| 4 | #include <linux/debugfs.h>
|
| 5 | #include <linux/slab.h>
|
| 6 | #include <linux/mm.h>
|
| 7 | #include "slab.h"
|
| 8 |
|
| 9 | static struct {
|
| 10 | struct fault_attr attr;
|
| 11 | bool ignore_gfp_reclaim;
|
| 12 | bool cache_filter;
|
| 13 | } failslab = {
|
| 14 | .attr = FAULT_ATTR_INITIALIZER,
|
| 15 | .ignore_gfp_reclaim = true,
|
| 16 | .cache_filter = false,
|
| 17 | };
|
| 18 |
|
| 19 | int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
|
| 20 | {
|
| 21 | int flags = 0;
|
| 22 |
|
| 23 |
|
| 24 | if (unlikely(s == kmem_cache))
|
| 25 | return 0;
|
| 26 |
|
| 27 | if (gfpflags & __GFP_NOFAIL)
|
| 28 | return 0;
|
| 29 |
|
| 30 | if (failslab.ignore_gfp_reclaim &&
|
| 31 | (gfpflags & __GFP_DIRECT_RECLAIM))
|
| 32 | return 0;
|
| 33 |
|
| 34 | if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB))
|
| 35 | return 0;
|
| 36 |
|
| 37 | |
| 38 | * In some cases, it expects to specify __GFP_NOWARN
|
| 39 | * to avoid printing any information(not just a warning),
|
| 40 | * thus avoiding deadlocks. See commit 6b9dbedbe349 for
|
| 41 | * details.
|
| 42 |
|
| 43 | if (gfpflags & __GFP_NOWARN)
|
| 44 | flags |= FAULT_NOWARN;
|
| 45 |
|
| 46 | return should_fail_ex(&failslab.attr, s->object_size, flags) ? -ENOMEM : 0;
|
| 47 | }
|
| 48 | ALLOW_ERROR_INJECTION(should_failslab, ERRNO);
|
| 49 |
|
| 50 | static int __init setup_failslab(char *str)
|
| 51 | {
|
| 52 | return setup_fault_attr(&failslab.attr, str);
|
| 53 | }
|
| 54 | __setup("failslab=", setup_failslab);
|
| 55 |
|
| 56 | #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
|
| 57 | static int __init failslab_debugfs_init(void)
|
| 58 | {
|
| 59 | struct dentry *dir;
|
| 60 | umode_t mode = S_IFREG | 0600;
|
| 61 |
|
| 62 | dir = fault_create_debugfs_attr("failslab", NULL, &failslab.attr);
|
| 63 | if (IS_ERR(dir))
|
| 64 | return PTR_ERR(dir);
|
| 65 |
|
| 66 | debugfs_create_bool("ignore-gfp-wait", mode, dir,
|
| 67 | &failslab.ignore_gfp_reclaim);
|
| 68 | debugfs_create_bool("cache-filter", mode, dir,
|
| 69 | &failslab.cache_filter);
|
| 70 |
|
| 71 | return 0;
|
| 72 | }
|
| 73 |
|
| 74 | late_initcall(failslab_debugfs_init);
|
| 75 |
|
| 76 | #endif
|