]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
mm/filemap: drop streaming/uncached pages when writeback completes
authorJens Axboe <axboe@kernel.dk>
Fri, 20 Dec 2024 15:47:47 +0000 (08:47 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 26 Jan 2025 04:22:43 +0000 (20:22 -0800)
If the folio is marked as streaming, drop pages when writeback completes.
Intended to be used with RWF_DONTCACHE, to avoid needing sync writes for
uncached IO.

Link: https://lkml.kernel.org/r/20241220154831.1086649-10-axboe@kernel.dk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Cc: Brian Foster <bfoster@redhat.com>
Cc: Chris Mason <clm@meta.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/filemap.c

index 9eade935a48cff034621beed4015e25534273a57..fb17b573ae51684ad2f51ddfea5124a979abd5fa 100644 (file)
@@ -1571,6 +1571,27 @@ int folio_wait_private_2_killable(struct folio *folio)
 }
 EXPORT_SYMBOL(folio_wait_private_2_killable);
 
+/*
+ * If folio was marked as dropbehind, then pages should be dropped when writeback
+ * completes. Do that now. If we fail, it's likely because of a big folio -
+ * just reset dropbehind for that case and latter completions should invalidate.
+ */
+static void folio_end_dropbehind_write(struct folio *folio)
+{
+       /*
+        * Hitting !in_task() should not happen off RWF_DONTCACHE writeback,
+        * but can happen if normal writeback just happens to find dirty folios
+        * that were created as part of uncached writeback, and that writeback
+        * would otherwise not need non-IRQ handling. Just skip the
+        * invalidation in that case.
+        */
+       if (in_task() && folio_trylock(folio)) {
+               if (folio->mapping)
+                       folio_unmap_invalidate(folio->mapping, folio, 0);
+               folio_unlock(folio);
+       }
+}
+
 /**
  * folio_end_writeback - End writeback against a folio.
  * @folio: The folio.
@@ -1581,6 +1602,8 @@ EXPORT_SYMBOL(folio_wait_private_2_killable);
  */
 void folio_end_writeback(struct folio *folio)
 {
+       bool folio_dropbehind = false;
+
        VM_BUG_ON_FOLIO(!folio_test_writeback(folio), folio);
 
        /*
@@ -1602,9 +1625,14 @@ void folio_end_writeback(struct folio *folio)
         * reused before the folio_wake_bit().
         */
        folio_get(folio);
+       if (!folio_test_dirty(folio))
+               folio_dropbehind = folio_test_clear_dropbehind(folio);
        if (__folio_end_writeback(folio))
                folio_wake_bit(folio, PG_writeback);
        acct_reclaim_writeback(folio);
+
+       if (folio_dropbehind)
+               folio_end_dropbehind_write(folio);
        folio_put(folio);
 }
 EXPORT_SYMBOL(folio_end_writeback);