From: Baokun Li In __alloc_pages_slowpath(), allocating page units larger than order-1 with __GFP_NOFAIL may trigger an unexpected WARN_ON. To prevent this, handle the case explicitly in jbd2_alloc(), ensuring that the warning does not occur after enabling BS > PS support. Signed-off-by: Baokun Li Reviewed-by: Zhang Yi --- fs/jbd2/journal.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index d480b94117cd..9185f9e2b201 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -2761,14 +2761,36 @@ static struct kmem_cache *get_slab(size_t size) void *jbd2_alloc(size_t size, gfp_t flags) { void *ptr; + int order; BUG_ON(size & (size-1)); /* Must be a power of 2 */ - if (size < PAGE_SIZE) + if (size < PAGE_SIZE) { ptr = kmem_cache_alloc(get_slab(size), flags); - else - ptr = (void *)__get_free_pages(flags, get_order(size)); + goto out; + } + + /* + * Allocating page units greater than order-1 with __GFP_NOFAIL in + * __alloc_pages_slowpath() can trigger an unexpected WARN_ON. + * Handle this case separately to suppress the warning. + */ + order = get_order(size); + if (order <= 1) { + ptr = (void *)__get_free_pages(flags, order); + goto out; + } + while (1) { + ptr = (void *)__get_free_pages(flags & ~__GFP_NOFAIL, order); + if (ptr) + break; + if (!(flags & __GFP_NOFAIL)) + break; + memalloc_retry_wait(flags); + } + +out: /* Check alignment; SLUB has gotten this wrong in the past, * and this can lead to user data corruption! */ BUG_ON(((unsigned long) ptr) & (size-1)); -- 2.46.1