On Wed, Nov 25, 2020 at 04:11:57PM -0800, Hugh Dickins wrote: > The little fix definitely needed was shown by generic/083: each > fsstress waiting for page lock, happens even without forcing huge > pages. See below... Huh ... I need to look into why my xfstests run is skipping generic/083: 0006 generic/083 3s ... run fstests generic/083 at 2020-11-26 12:11:52 0006 [not run] this test requires a valid $SCRATCH_MNT and unique 0006 Ran: generic/083 0006 Not run: generic/083 > > if (!unfalloc || !PageUptodate(page)) { > > if (page_mapping(page) != mapping) { > > /* Page was replaced by swap: retry */ > > unlock_page(page); > > - index--; > > + put_page(page); > > break; > > } > > VM_BUG_ON_PAGE(PageWriteback(page), page); > > - if (shmem_punch_compound(page, start, end)) > > - truncate_inode_page(mapping, page); > > - else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { > > - /* Wipe the page and don't get stuck */ > > - clear_highpage(page); > > - flush_dcache_page(page); > > - set_page_dirty(page); > > - if (index < > > - round_up(start, HPAGE_PMD_NR)) > > - start = index + 1; > > - } > > + index = truncate_inode_partial_page(mapping, > > + page, lstart, lend); > > + if (index > end) > > + end = indices[i] - 1; > > } > > - unlock_page(page); > > The fix needed is here: instead of deleting that unlock_page(page) > line, it needs to be } else { unlock_page(page); } It also needs a put_page(page); That's now taken care of by truncate_inode_partial_page(), so if we're not calling that, we need to put the page as well. ie this: +++ b/mm/shmem.c @@ -954,6 +954,9 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, page, lstart, lend); if (index > end) end = indices[i] - 1; + } else { + unlock_page(page); + put_page(page); } } index = indices[i - 1] + 1; > > } > > + index = indices[i - 1] + 1; > > pagevec_remove_exceptionals(&pvec); > > - pagevec_release(&pvec); > > - index++; > > + pagevec_reinit(&pvec);