From: "Matthew Wilcox (Oracle)" <wi...@infradead.org>

If the page is being replaced with a NULL, we can do a single store that
erases the entire range of indices.  Otherwise we have to use a loop to
store one shadow entry in each index.

Signed-off-by: Matthew Wilcox (Oracle) <wi...@infradead.org>
---
 mm/filemap.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 78f888d028c5..17db007f0277 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -120,22 +120,27 @@ static void page_cache_delete(struct address_space 
*mapping,
                                   struct page *page, void *shadow)
 {
        XA_STATE(xas, &mapping->i_pages, page->index);
-       unsigned int nr = 1;
+       unsigned int i, nr = 1, entries = 1;
 
        mapping_set_update(&xas, mapping);
 
        /* hugetlb pages are represented by a single entry in the xarray */
        if (!PageHuge(page)) {
-               xas_set_order(&xas, page->index, compound_order(page));
-               nr = compound_nr(page);
+               entries = nr = thp_nr_pages(page);
+               if (!shadow) {
+                       xas_set_order(&xas, page->index, thp_order(page));
+                       entries = 1;
+               }
        }
 
        VM_BUG_ON_PAGE(!PageLocked(page), page);
        VM_BUG_ON_PAGE(PageTail(page), page);
-       VM_BUG_ON_PAGE(nr != 1 && shadow, page);
 
-       xas_store(&xas, shadow);
-       xas_init_marks(&xas);
+       for (i = 0; i < entries; i++) {
+               xas_store(&xas, shadow);
+               xas_init_marks(&xas);
+               xas_next(&xas);
+       }
 
        page->mapping = NULL;
        /* Leave page->index set: truncation lookup relies upon it */
-- 
2.26.2

Reply via email to