diff mbox series

[5.10,2/2] mm/truncate: Replace page_mapped() call in invalidate_inode_page()

Message ID 20240111143747.4418-3-r.smirnov@omp.ru (mailing list archive)
State New
Headers show
Series mm/truncate: fix issue in ext4_set_page_dirty() | expand

Commit Message

Roman Smirnov Jan. 11, 2024, 2:37 p.m. UTC
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

Commit e41c81d0d30e1a6ebf408feaf561f80cac4457dc upstream.

folio_mapped() is expensive because it has to check each page's mapcount
field.  A cheaper check is whether there are any extra references to
the page, other than the one we own, one from the page private data and
the ones held by the page cache.

The call to remove_mapping() will fail in any case if it cannot freeze
the refcount, but failing here avoids cycling the i_pages spinlock.

[Roman: replaced folio_ref_count() call with page_ref_count(),
folio_nr_pages() call with compound_nr() and
folio_has_private() call with page_has_private()]

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Miaohe Lin <linmiaohe@huawei.com>
Signed-off-by: Roman Smirnov <r.smirnov@omp.ru>
---
 mm/truncate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/mm/truncate.c b/mm/truncate.c
index 03998fd86e4a..72d6c62756fd 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -232,7 +232,8 @@  int invalidate_inode_page(struct page *page)
 		return 0;
 	if (PageDirty(page) || PageWriteback(page))
 		return 0;
-	if (page_mapped(page))
+	if (page_ref_count(page) >
+			compound_nr(page) + page_has_private(page) + 1)
 		return 0;
 	if (page_has_private(page) && !try_to_release_page(page, 0))
 		return 0;