diff options
author | Matthew Wilcox (Oracle) <willy@infradead.org> | 2022-02-12 17:43:16 -0500 |
---|---|---|
committer | Matthew Wilcox (Oracle) <willy@infradead.org> | 2022-03-21 12:59:01 -0400 |
commit | e41c81d0d30e1a6ebf408feaf561f80cac4457dc (patch) | |
tree | 4337c6160315b516d9c58241832a235f6656a93f /mm/truncate.c | |
parent | 4418481396b2caeded6d0eed11ac9052ab4c0763 (diff) | |
download | lwn-e41c81d0d30e1a6ebf408feaf561f80cac4457dc.tar.gz lwn-e41c81d0d30e1a6ebf408feaf561f80cac4457dc.zip |
mm/truncate: Replace page_mapped() call in invalidate_inode_page()
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.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Miaohe Lin <linmiaohe@huawei.com>
Diffstat (limited to 'mm/truncate.c')
-rw-r--r-- | mm/truncate.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index b73c30c95cd0..06b7a4ca2370 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -287,7 +287,9 @@ int invalidate_inode_page(struct page *page) return 0; if (folio_test_dirty(folio) || folio_test_writeback(folio)) return 0; - if (page_mapped(page)) + /* The refcount will be elevated if any page in the folio is mapped */ + if (folio_ref_count(folio) > + folio_nr_pages(folio) + folio_has_private(folio) + 1) return 0; if (folio_has_private(folio) && !filemap_release_folio(folio, 0)) return 0; |