Thread (22 messages) flat view 22 messages, 6 authors, 1h ago

Re: [PATCH 1/3] md: Use folio_alloc_buffers()

From: sashiko-bot@kernel.org
Date: 2026-09-14 04:27:47

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Severe memory leak of bitmap pages in free_buffers() when PagePrivate is not set.
--

commit 9822ba9b718b51ce47732b5412e326f063b30c60
Author: Matthew Wilcox (Oracle) [off-list ref]

md: Use folio_alloc_buffers()

This commit removes the last user of alloc_page_buffers(), replacing it
with folio_alloc_buffers() to prevent new callers from existing.
quoted hunk ↗ jump to hunk
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index b8325cb09a371..5f1637f974c15 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -560,6 +560,7 @@ static int read_file_page(struct file *file, unsigned long index,
 {
 	int ret = 0;
 	struct inode *inode = file_inode(file);
+	struct folio *folio = page_folio(page);
 	struct buffer_head *bh;
 	sector_t block, blk_cur;
 	unsigned long blocksize = i_blocksize(inode);
@@ -567,12 +568,12 @@ static int read_file_page(struct file *file, unsigned long index,
 	pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
 		 (unsigned long long)index << PAGE_SHIFT);
 
-	bh = alloc_page_buffers(page, blocksize);
+	bh = folio_alloc_buffers(folio, blocksize, GFP_NOFS | __GFP_ACCOUNT);
 	if (!bh) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	attach_page_private(page, bh);
+	folio_attach_private(folio, bh);
[Severity: High]
This isn't a bug introduced by this patch, but it is a severe pre-existing
resource leak in the cleanup path for these pages.

md_bitmap_storage_alloc() allocates pages via alloc_page() for
store->filemap. On teardown, md_bitmap_file_unmap() iterates over these
pages and calls free_buffers() to clean them up.

For internal bitmaps, read_sb_page() uses raw bios and never attaches
buffer heads, so the pages never have the PagePrivate flag set. 
When this happens, free_buffers() returns early:

static void free_buffers(struct page *page)
{
	struct buffer_head *bh;

	if (!PagePrivate(page))
		return;
...
	detach_page_private(page);
	put_page(page);
}

Does this early return mistakenly skip the final put_page() call,
permanently leaking the page when no buffer heads are attached?

This leaks memory pages allocated for the MD bitmap every time an array
with an internal bitmap is stopped, potentially leading to memory
exhaustion.

I verified that the follow-up patches in this series (which migrate this
function to the folio API) faithfully reproduce the exact same leak by
returning early when bh is NULL before calling folio_put(folio).

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260913-remove-pg_private-v4-0-848550f7574e@nvidia.com?part=1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help