On Tue, Mar 26, 2024 at 8:21 PM Matthew Wilcox <willy@xxxxxxxxxxxxx> wrote: > > On Tue, Mar 26, 2024 at 05:06:55PM +0800, Zhaoyang Huang wrote: > > 1. Thread_readahead remove the folio from page cache and drop 2 refcnt > > by readahead_folio & filemap_remove_folio(get rid of the folios which > > failed to launch IO during readahead) > > refcnt == 0, PG_lru == true, PG_lock == true > > read_pages > > ... > > folio = readahead_folio > > <one refcnt dropped here> > > ********For the folio which can not launch IO, we should NOT drop > > refcnt here??? replaced by __readahead_folio???********** > > folio_get > > filemap_remove_folio(folio) > > folio_unlock > > <one refcnt dropped here> > > folio_put > > Ignoring any other thread, you're basically saying that there's a > refcount imbalance here. Which means we'd hit an assert (that folio > refcount went below zero) in the normal case where another thread wasn't > simultaneously trying to do anything. Theoretically Yes but it is rare in practice as aops->readahead will launch all pages to IO under most scenarios. read_pages aops->readahead[1] ... while (folio = readahead_folio)[2] filemap_remove_folio IMO, according to the comments of readahead_page, the refcnt represents page cache dropped in [1] makes sense for two reasons, '1. The folio is going to do IO and is locked until IO done;2. The refcnt will be added back when found again from the page cache and then serve for PTE or vfs' while it doesn't make sense in [2] as the refcnt of page cache will be dropped in filemap_remove_folio * Context: The page is locked and has an elevated refcount. The caller * should decreases the refcount once the page has been submitted for I/O * and unlock the page once all I/O to that page has completed. * Return: A pointer to the next page, or %NULL if we are done.