]> git.baikalelectronics.ru Git - kernel.git/commitdiff
filemap: Don't release a locked folio
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Tue, 7 Jun 2022 19:45:53 +0000 (15:45 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 9 Jun 2022 20:24:25 +0000 (16:24 -0400)
We must hold a reference over the call to filemap_release_folio(),
otherwise the page cache will put the last reference to the folio
before we unlock it, leading to splats like this:

 BUG: Bad page state in process u8:5  pfn:1ab1f4
 page:ffffea0006ac7d00 refcount:0 mapcount:0 mapping:0000000000000000 index:0x28b1de pfn:0x1ab1f4
 flags: 0x17ff80000040001(locked|reclaim|node=0|zone=2|lastcpupid=0xfff)
 raw: 017ff80000040001 dead000000000100 dead000000000122 0000000000000000
 raw: 000000000028b1de 0000000000000000 00000000ffffffff 0000000000000000
 page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set

It's an error path, so it doesn't see much testing.

Reported-by: Darrick J. Wong <djwong@kernel.org>
Fixes: ca2caef9893d ("readahead: Use a folio in read_pages()")
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
mm/readahead.c

index 415c39d764eaebc0696f270ef5a98117c8e51348..57a0151082543cb67b08d7c1721f62b1e10c6678 100644 (file)
@@ -164,12 +164,14 @@ static void read_pages(struct readahead_control *rac)
                while ((folio = readahead_folio(rac)) != NULL) {
                        unsigned long nr = folio_nr_pages(folio);
 
+                       folio_get(folio);
                        rac->ra->size -= nr;
                        if (rac->ra->async_size >= nr) {
                                rac->ra->async_size -= nr;
                                filemap_remove_folio(folio);
                        }
                        folio_unlock(folio);
+                       folio_put(folio);
                }
        } else {
                while ((folio = readahead_folio(rac)) != NULL)