On Thu, Apr 07, 2022 at 07:41:47AM +0100, David Howells wrote: > Matthew Wilcox <willy@xxxxxxxxxxxxx> wrote: > > > On Thu, Apr 07, 2022 at 12:05:05AM +0100, David Howells wrote: > > > Fix this by adding an extra address_space operation, ->removing folio(), > > > and flag, AS_NOTIFY_REMOVING_FOLIO. The operation is called if the flag is > > > set when a folio is removed from the pagecache. The flag should be set if > > > a non-NULL cookie is obtained from fscache and cleared in ->evict_inode() > > > before truncate_inode_pages_final() is called. > > > > What's wrong with ->freepage? > > It's too late. The optimisation must be cancelled before there's a chance > that a new page can be allocated and attached to the pagecache - but > ->freepage() is called after the folio has been removed. Doing it in > ->freepage() would allow ->readahead(), ->readpage() or ->write_begin() to > jump in and start a new read (which gets skipped because the optimisation is > still in play). OK. You suggested that releasepage was an acceptable place to call it. How about we have AS_RELEASE_ALL (... or something ...) and then page_has_private() becomes a bit more complicated ... to the point where we should probably get rid of it (by embedding it into filemap_release_folio(): +++ b/mm/filemap.c @@ -3981,6 +3981,9 @@ bool filemap_release_folio(struct folio *folio, gfp_t gfp) struct address_space * const mapping = folio->mapping; BUG_ON(!folio_test_locked(folio)); + if (!mapping_needs_release(mapping) && !folio_test_private(folio) && + !folio_test_private_2(folio)) + return false; if (folio_test_writeback(folio)) return false;