[PATCH 23/25] jbd2: prevent WARN_ON in __alloc_pages_slowpath() when BS > PS

libaokun@huaweicloud.com posted 25 patches 3 months, 2 weeks ago
There is a newer version of this series
[PATCH 23/25] jbd2: prevent WARN_ON in __alloc_pages_slowpath() when BS > PS
Posted by libaokun@huaweicloud.com 3 months, 2 weeks ago
From: Baokun Li <libaokun1@huawei.com>

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 <libaokun1@huawei.com>
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
---
 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