If we're going to unmap a THP, we have to be sure to unmap the entire page, not just the part of it which lies after the search index. Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> --- mm/truncate.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/mm/truncate.c b/mm/truncate.c index 27cf411ae51f..30653b2717d3 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -652,6 +652,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, while (find_get_entries(mapping, index, end, &pvec, indices)) { for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; + pgoff_t count; /* We rely upon deletion not changing page->index */ index = indices[i]; @@ -664,27 +665,22 @@ int invalidate_inode_pages2_range(struct address_space *mapping, } lock_page(page); - WARN_ON(page_to_index(page) != index); if (page->mapping != mapping) { unlock_page(page); continue; } wait_on_page_writeback(page); + count = thp_nr_pages(page); + index = page->index + count - 1; if (page_mapped(page)) { if (!did_range_unmap) { - /* - * Zap the rest of the file in one hit. - */ - unmap_mapping_pages(mapping, index, - (1 + end - index), false); + /* Zap the rest of the file */ + count = max(count, + end - page->index + 1); did_range_unmap = 1; - } else { - /* - * Just zap this page - */ - unmap_mapping_pages(mapping, index, - 1, false); } + unmap_mapping_pages(mapping, page->index, + count, false); } BUG_ON(page_mapped(page)); ret2 = do_launder_page(mapping, page); -- 2.28.0