18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/fault-inject.h> 38c2ecf20Sopenharmony_ci#include <linux/slab.h> 48c2ecf20Sopenharmony_ci#include <linux/mm.h> 58c2ecf20Sopenharmony_ci#include "slab.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_cistatic struct { 88c2ecf20Sopenharmony_ci struct fault_attr attr; 98c2ecf20Sopenharmony_ci bool ignore_gfp_reclaim; 108c2ecf20Sopenharmony_ci bool cache_filter; 118c2ecf20Sopenharmony_ci} failslab = { 128c2ecf20Sopenharmony_ci .attr = FAULT_ATTR_INITIALIZER, 138c2ecf20Sopenharmony_ci .ignore_gfp_reclaim = true, 148c2ecf20Sopenharmony_ci .cache_filter = false, 158c2ecf20Sopenharmony_ci}; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cibool __should_failslab(struct kmem_cache *s, gfp_t gfpflags) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci /* No fault-injection for bootstrap cache */ 208c2ecf20Sopenharmony_ci if (unlikely(s == kmem_cache)) 218c2ecf20Sopenharmony_ci return false; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci if (gfpflags & __GFP_NOFAIL) 248c2ecf20Sopenharmony_ci return false; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (failslab.ignore_gfp_reclaim && 278c2ecf20Sopenharmony_ci (gfpflags & __GFP_DIRECT_RECLAIM)) 288c2ecf20Sopenharmony_ci return false; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB)) 318c2ecf20Sopenharmony_ci return false; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci return should_fail(&failslab.attr, s->object_size); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int __init setup_failslab(char *str) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci return setup_fault_attr(&failslab.attr, str); 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci__setup("failslab=", setup_failslab); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS 438c2ecf20Sopenharmony_cistatic int __init failslab_debugfs_init(void) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct dentry *dir; 468c2ecf20Sopenharmony_ci umode_t mode = S_IFREG | 0600; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci dir = fault_create_debugfs_attr("failslab", NULL, &failslab.attr); 498c2ecf20Sopenharmony_ci if (IS_ERR(dir)) 508c2ecf20Sopenharmony_ci return PTR_ERR(dir); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci debugfs_create_bool("ignore-gfp-wait", mode, dir, 538c2ecf20Sopenharmony_ci &failslab.ignore_gfp_reclaim); 548c2ecf20Sopenharmony_ci debugfs_create_bool("cache-filter", mode, dir, 558c2ecf20Sopenharmony_ci &failslab.cache_filter); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci return 0; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cilate_initcall(failslab_debugfs_init); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ 63