Introduce a mechanism to dynamically boost watermarks when critical atomic allocations (GFP_ATOMIC, order-0) fail. This prevents recurring network packet drops or other atomic failures by proactively triggering kswapd to reclaim memory for future atomic requests. The mechanism utilizes the existing watermark_boost infrastructure. When an order-0 atomic allocation fails, watermarks are boosted in the relevant zones, which encourages kswapd to reclaim pages more aggressively. Boosting is debounced to once every 10 seconds to prevent adjustment storms during burst traffic. Testing has shown that this allows the system to recover quickly from sudden spikes in network traffic that otherwise would cause persistent allocation failures. Observed failure logs: [38535641.026406] node 0: slabs: 941, objs: 54656, free: 0 [38535641.037711] node 1: slabs: 349, objs: 22096, free: 272 [38535641.049025] node 1: slabs: 349, objs: 22096, free: 272 [38535642.795972] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC) [38535642.805017] cache: skbuff_head_cache, object size: 232, buffer size: 256, default order: 2, min order: 0 [38535642.816311] node 0: slabs: 854, objs: 42320, free: 0 [38535642.823066] node 1: slabs: 400, objs: 25360, free: 294 [38535643.070199] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC) [38535643.078861] cache: skbuff_head_cache, object size: 232, buffer size: 256, default order: 2, min order: 0 [38535643.089719] node 0: slabs: 841, objs: 41824, free: 0 [38535643.096513] node 1: slabs: 393, objs: 24480, free: 272 [38535643.484149] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC) [38535643.492831] cache: skbuff_head_cache, object size: 232, buffer size: 256, default order: 2, min order: 0 [38535643.503666] node 0: slabs: 898, objs: 43120, free: 159 [38535643.510140] node 1: slabs: 404, objs: 25424, free: 319 [38535644.699224] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC) [38535644.707911] cache: skbuff_head_cache, object size: 232, buffer size: 256, default order: 2, min order: 0 [38535644.718700] node 0: slabs: 1031, objs: 43328, free: 0 [38535644.725059] node 1: slabs: 339, objs: 17616, free: 317 [38535645.428345] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC) [38535645.436888] cache: skbuff_head_cache, object size: 232, buffer size: 256, default order: 2, min order: 0 [38535645.447664] node 0: slabs: 940, objs: 40864, free: 144 [38535645.454026] node 1: slabs: 322, objs: 19168, free: 383 [38535645.556122] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC) [38535645.564576] cache: skbuff_head_cache, object size: 232, buffer size: 256, default order: 2, min order: 0 [38535649.655523] warn_alloc: 59 callbacks suppressed [38535649.655527] swapper/100: page allocation failure: order:0, mode:0x480020(GFP_ATOMIC), nodemask=(null) [38535649.671692] swapper/100 cpuset=/ mems_allowed=0-1 Signed-off-by: wujing Signed-off-by: Qiliang Yuan --- mm/page_alloc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c380f063e8b7..a2959fee28d9 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3975,6 +3975,10 @@ static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask) mem_cgroup_show_protected_memory(NULL); } +/* Auto-tuning watermarks on atomic allocation failures */ +static unsigned long last_boost_jiffies = 0; +#define BOOST_DEBOUNCE_MS 10000 /* 10 seconds debounce */ + void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...) { struct va_format vaf; @@ -4947,6 +4951,22 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, goto retry; } fail: + /* Auto-tuning: boost watermarks if atomic allocation fails */ + if ((gfp_mask & GFP_ATOMIC) && order == 0) { + unsigned long now = jiffies; + + if (time_after(now, last_boost_jiffies + msecs_to_jiffies(BOOST_DEBOUNCE_MS))) { + struct zoneref *z; + struct zone *zone; + + last_boost_jiffies = now; + for_each_zone_zonelist(zone, z, ac->zonelist, ac->highest_zoneidx) { + if (boost_watermark(zone)) + wakeup_kswapd(zone, gfp_mask, 0, ac->highest_zoneidx); + } + } + } + warn_alloc(gfp_mask, ac->nodemask, "page allocation failure: order:%u", order); got_pg: -- 2.39.5