Frag allocator is not designed for fragsz > PAGE_SIZE. So, check and return the error at the beginning of __page_frag_alloc_align(), instead of succeed for a few times, then fail due to not refilling the cache.
Signed-off-by: Haiyang Zhang <haiya...@microsoft.com> --- mm/page_frag_cache.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/mm/page_frag_cache.c b/mm/page_frag_cache.c index d2423f30577e..d6bf022087e7 100644 --- a/mm/page_frag_cache.c +++ b/mm/page_frag_cache.c @@ -98,6 +98,15 @@ void *__page_frag_alloc_align(struct page_frag_cache *nc, unsigned int size, offset; struct page *page; + if (unlikely(fragsz > PAGE_SIZE)) { + /* + * The caller is trying to allocate a fragment + * with fragsz > PAGE_SIZE which is not supported + * by design. So we simply return NULL here. + */ + return NULL; + } + if (unlikely(!encoded_page)) { refill: page = __page_frag_cache_refill(nc, gfp_mask); @@ -119,19 +128,6 @@ void *__page_frag_alloc_align(struct page_frag_cache *nc, size = PAGE_SIZE << encoded_page_decode_order(encoded_page); offset = __ALIGN_KERNEL_MASK(nc->offset, ~align_mask); if (unlikely(offset + fragsz > size)) { - if (unlikely(fragsz > PAGE_SIZE)) { - /* - * The caller is trying to allocate a fragment - * with fragsz > PAGE_SIZE but the cache isn't big - * enough to satisfy the request, this may - * happen in low memory conditions. - * We don't release the cache page because - * it could make memory pressure worse - * so we simply return NULL here. - */ - return NULL; - } - page = encoded_page_decode_page(encoded_page); if (!page_ref_sub_and_test(page, nc->pagecnt_bias)) -- 2.34.1