On Tue, Sep 29, 2020 at 10:58:55AM +0200, Jan Kara wrote: > On Mon 14-09-20 14:00:35, Matthew Wilcox (Oracle) wrote: > > We have three functions (shmem_undo_range(), truncate_inode_pages_range() > > and invalidate_mapping_pages()) which want exactly this function, so > > add it to filemap.c. > > > > Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> > > diff --git a/mm/shmem.c b/mm/shmem.c > ... > > index b65263d9bb67..a73ce8ce28e3 100644 > > --- a/mm/shmem.c > > +++ b/mm/shmem.c > > @@ -905,12 +905,8 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, > > > > pagevec_init(&pvec); > > index = start; > > - while (index < end) { > > - pvec.nr = find_get_entries(mapping, index, > > - min(end - index, (pgoff_t)PAGEVEC_SIZE), > > - pvec.pages, indices); > > - if (!pvec.nr) > > - break; > > + while (index < end && find_lock_entries(mapping, index, end - 1, > > + &pvec, indices)) { > > for (i = 0; i < pagevec_count(&pvec); i++) { > > struct page *page = pvec.pages[i]; > > > > @@ -925,18 +921,10 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, > > index, page); > > continue; > > } > > + index += thp_nr_pages(page) - 1; > > > > - VM_BUG_ON_PAGE(page_to_pgoff(page) != index, page); > > - > > - if (!trylock_page(page)) > > - continue; > > - > > - if ((!unfalloc || !PageUptodate(page)) && > > - page_mapping(page) == mapping) { > > - VM_BUG_ON_PAGE(PageWriteback(page), page); > > - if (shmem_punch_compound(page, start, end)) > > - truncate_inode_page(mapping, page); > > - } > > + if (!unfalloc || !PageUptodate(page)) > > + truncate_inode_page(mapping, page); > > Is dropping shmem_punch_compound() really safe? AFAICS it can also call > split_huge_page() which will try to split THP to be able to truncate it. > That being said there's another loop in shmem_undo_range() which will try > again so what you did might make a difference with performance but not much > else. But still it would be good to at least comment about this in the > changelog... OK, I need to provide better argumentation in the changelog. shmem_punch_compound() handles partial THPs. By the end of this series, we handle the partial pages in the next part of the function ... the part where we're handling partial PAGE_SIZE pages. At this point in the series, it's safe to remove the shmem_punch_compound() call because the new find_lock_entries() loop will only return THPs that lie entirely within the range.