filemap: Add filemap_unaccount_folio()
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Sun, 9 May 2021 00:04:05 +0000 (20:04 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Tue, 4 Jan 2022 18:15:33 +0000 (13:15 -0500)
Replace unaccount_page_cache_page() with filemap_unaccount_folio().
The bug handling path could be a bit more robust (eg taking into account
the mapcounts of tail pages), but it's really never supposed to happen.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: William Kucharski <william.kucharski@oracle.com>
include/linux/pagemap.h
mm/filemap.c

index 841f7ba62d7d20435813c806d5da3a50e7951286..077b6f378666c198a16f8a3bd80ad5ef8ee7547a 100644 (file)
@@ -884,11 +884,6 @@ static inline void __set_page_dirty(struct page *page,
 }
 void folio_account_cleaned(struct folio *folio, struct address_space *mapping,
                          struct bdi_writeback *wb);
-static inline void account_page_cleaned(struct page *page,
-               struct address_space *mapping, struct bdi_writeback *wb)
-{
-       return folio_account_cleaned(page_folio(page), mapping, wb);
-}
 void __folio_cancel_dirty(struct folio *folio);
 static inline void folio_cancel_dirty(struct folio *folio)
 {
index 38fb26e16b8595ed40fe81207701567de7fa53e8..600b8c921a674c0153ad80c64963d0d3403de1ec 100644 (file)
@@ -145,74 +145,74 @@ static void page_cache_delete(struct address_space *mapping,
        mapping->nrpages -= nr;
 }
 
-static void unaccount_page_cache_page(struct address_space *mapping,
-                                     struct page *page)
+static void filemap_unaccount_folio(struct address_space *mapping,
+               struct folio *folio)
 {
-       int nr;
+       long nr;
 
        /*
         * if we're uptodate, flush out into the cleancache, otherwise
         * invalidate any existing cleancache entries.  We can't leave
         * stale data around in the cleancache once our page is gone
         */
-       if (PageUptodate(page) && PageMappedToDisk(page))
-               cleancache_put_page(page);
+       if (folio_test_uptodate(folio) && folio_test_mappedtodisk(folio))
+               cleancache_put_page(&folio->page);
        else
-               cleancache_invalidate_page(mapping, page);
+               cleancache_invalidate_page(mapping, &folio->page);
 
-       VM_BUG_ON_PAGE(PageTail(page), page);
-       VM_BUG_ON_PAGE(page_mapped(page), page);
-       if (!IS_ENABLED(CONFIG_DEBUG_VM) && unlikely(page_mapped(page))) {
+       VM_BUG_ON_FOLIO(folio_mapped(folio), folio);
+       if (!IS_ENABLED(CONFIG_DEBUG_VM) && unlikely(folio_mapped(folio))) {
                int mapcount;
 
                pr_alert("BUG: Bad page cache in process %s  pfn:%05lx\n",
-                        current->comm, page_to_pfn(page));
-               dump_page(page, "still mapped when deleted");
+                        current->comm, folio_pfn(folio));
+               dump_page(&folio->page, "still mapped when deleted");
                dump_stack();
                add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
 
-               mapcount = page_mapcount(page);
+               mapcount = page_mapcount(&folio->page);
                if (mapping_exiting(mapping) &&
-                   page_count(page) >= mapcount + 2) {
+                   folio_ref_count(folio) >= mapcount + 2) {
                        /*
                         * All vmas have already been torn down, so it's
-                        * a good bet that actually the page is unmapped,
+                        * a good bet that actually the folio is unmapped,
                         * and we'd prefer not to leak it: if we're wrong,
                         * some other bad page check should catch it later.
                         */
-                       page_mapcount_reset(page);
-                       page_ref_sub(page, mapcount);
+                       page_mapcount_reset(&folio->page);
+                       folio_ref_sub(folio, mapcount);
                }
        }
 
-       /* hugetlb pages do not participate in page cache accounting. */
-       if (PageHuge(page))
+       /* hugetlb folios do not participate in page cache accounting. */
+       if (folio_test_hugetlb(folio))
                return;
 
-       nr = thp_nr_pages(page);
+       nr = folio_nr_pages(folio);
 
-       __mod_lruvec_page_state(page, NR_FILE_PAGES, -nr);
-       if (PageSwapBacked(page)) {
-               __mod_lruvec_page_state(page, NR_SHMEM, -nr);
-               if (PageTransHuge(page))
-                       __mod_lruvec_page_state(page, NR_SHMEM_THPS, -nr);
-       } else if (PageTransHuge(page)) {
-               __mod_lruvec_page_state(page, NR_FILE_THPS, -nr);
+       __lruvec_stat_mod_folio(folio, NR_FILE_PAGES, -nr);
+       if (folio_test_swapbacked(folio)) {
+               __lruvec_stat_mod_folio(folio, NR_SHMEM, -nr);
+               if (folio_test_pmd_mappable(folio))
+                       __lruvec_stat_mod_folio(folio, NR_SHMEM_THPS, -nr);
+       } else if (folio_test_pmd_mappable(folio)) {
+               __lruvec_stat_mod_folio(folio, NR_FILE_THPS, -nr);
                filemap_nr_thps_dec(mapping);
        }
 
        /*
-        * At this point page must be either written or cleaned by
-        * truncate.  Dirty page here signals a bug and loss of
+        * At this point folio must be either written or cleaned by
+        * truncate.  Dirty folio here signals a bug and loss of
         * unwritten data.
         *
-        * This fixes dirty accounting after removing the page entirely
-        * but leaves PageDirty set: it has no effect for truncated
-        * page and anyway will be cleared before returning page into
+        * This fixes dirty accounting after removing the folio entirely
+        * but leaves the dirty flag set: it has no effect for truncated
+        * folio and anyway will be cleared before returning folio to
         * buddy allocator.
         */
-       if (WARN_ON_ONCE(PageDirty(page)))
-               account_page_cleaned(page, mapping, inode_to_wb(mapping->host));
+       if (WARN_ON_ONCE(folio_test_dirty(folio)))
+               folio_account_cleaned(folio, mapping,
+                                       inode_to_wb(mapping->host));
 }
 
 /*
@@ -227,7 +227,7 @@ void __delete_from_page_cache(struct page *page, void *shadow)
 
        trace_mm_filemap_delete_from_page_cache(page);
 
-       unaccount_page_cache_page(mapping, page);
+       filemap_unaccount_folio(mapping, folio);
        page_cache_delete(mapping, folio, shadow);
 }
 
@@ -348,7 +348,7 @@ void delete_from_page_cache_batch(struct address_space *mapping,
        for (i = 0; i < pagevec_count(pvec); i++) {
                trace_mm_filemap_delete_from_page_cache(pvec->pages[i]);
 
-               unaccount_page_cache_page(mapping, pvec->pages[i]);
+               filemap_unaccount_folio(mapping, page_folio(pvec->pages[i]));
        }
        page_cache_delete_batch(mapping, pvec);
        xa_unlock_irq(&mapping->i_pages);