162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/fault-inject.h> 362306a36Sopenharmony_ci#include <linux/mm.h> 462306a36Sopenharmony_ci 562306a36Sopenharmony_cistatic struct { 662306a36Sopenharmony_ci struct fault_attr attr; 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci bool ignore_gfp_highmem; 962306a36Sopenharmony_ci bool ignore_gfp_reclaim; 1062306a36Sopenharmony_ci u32 min_order; 1162306a36Sopenharmony_ci} fail_page_alloc = { 1262306a36Sopenharmony_ci .attr = FAULT_ATTR_INITIALIZER, 1362306a36Sopenharmony_ci .ignore_gfp_reclaim = true, 1462306a36Sopenharmony_ci .ignore_gfp_highmem = true, 1562306a36Sopenharmony_ci .min_order = 1, 1662306a36Sopenharmony_ci}; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic int __init setup_fail_page_alloc(char *str) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci return setup_fault_attr(&fail_page_alloc.attr, str); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci__setup("fail_page_alloc=", setup_fail_page_alloc); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cibool __should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci int flags = 0; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (order < fail_page_alloc.min_order) 2962306a36Sopenharmony_ci return false; 3062306a36Sopenharmony_ci if (gfp_mask & __GFP_NOFAIL) 3162306a36Sopenharmony_ci return false; 3262306a36Sopenharmony_ci if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM)) 3362306a36Sopenharmony_ci return false; 3462306a36Sopenharmony_ci if (fail_page_alloc.ignore_gfp_reclaim && 3562306a36Sopenharmony_ci (gfp_mask & __GFP_DIRECT_RECLAIM)) 3662306a36Sopenharmony_ci return false; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* See comment in __should_failslab() */ 3962306a36Sopenharmony_ci if (gfp_mask & __GFP_NOWARN) 4062306a36Sopenharmony_ci flags |= FAULT_NOWARN; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci return should_fail_ex(&fail_page_alloc.attr, 1 << order, flags); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic int __init fail_page_alloc_debugfs(void) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci umode_t mode = S_IFREG | 0600; 5062306a36Sopenharmony_ci struct dentry *dir; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci dir = fault_create_debugfs_attr("fail_page_alloc", NULL, 5362306a36Sopenharmony_ci &fail_page_alloc.attr); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci debugfs_create_bool("ignore-gfp-wait", mode, dir, 5662306a36Sopenharmony_ci &fail_page_alloc.ignore_gfp_reclaim); 5762306a36Sopenharmony_ci debugfs_create_bool("ignore-gfp-highmem", mode, dir, 5862306a36Sopenharmony_ci &fail_page_alloc.ignore_gfp_highmem); 5962306a36Sopenharmony_ci debugfs_create_u32("min-order", mode, dir, &fail_page_alloc.min_order); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cilate_initcall(fail_page_alloc_debugfs); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ 67