From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: Christian Brauner <brauner@kernel.org>
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>,
Jan Kara <jack@suse.cz>, Chris Mason <clm@fb.com>,
David Sterba <dsterba@suse.com>,
Miklos Szeredi <miklos@szeredi.hu>,
Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>,
Mike Marshall <hubcap@omnibond.com>,
Martin Brandenburg <martin@omnibond.com>,
Alexander Viro <viro@zeniv.linux.org.uk>,
linux-fsdevel@vger.kernel.org, linux-mm@kvack.org,
linux-block@vger.kernel.org, linux-btrfs@vger.kernel.org,
fuse-devel@lists.linux.dev, linux-nfs@vger.kernel.org,
devel@lists.orangefs.org, Pavel Begunkov <asml.silence@gmail.com>
Subject: [PATCH 7/7] Remove folio_launder()
Date: Thu, 20 Aug 2026 20:33:40 +0100 [thread overview]
Message-ID: <20260820193343.3852967-8-willy@infradead.org> (raw)
In-Reply-To: <20260820193343.3852967-1-willy@infradead.org>
When we do direct I/O, we need to evict any page cache that overlaps
the range in the file. First we write back any dirty folios in the
range, then we lock each folio and remove it from the CPU page tables.
This leaves a wide window for userspace to re-dirty the folio by storing
to a shared writable mmap.
Many filesystems respond to this situation by failing the call to
release_folio(), but some try to writeback the dirty folio again, formerly
in their release_folio() method and now in their launder_folio() method.
Remove this inconsistency between filesystems by checking
whether the folio is dirty in the VFS and failing the call to
folio_unmap_invalidate(). Since we hold the folio locked and unmapped
at this time, there is no way to dirty the folio after this point.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
Documentation/filesystems/locking.rst | 8 --------
Documentation/filesystems/vfs.rst | 6 ------
include/linux/fs.h | 1 -
mm/truncate.c | 15 ++-------------
4 files changed, 2 insertions(+), 28 deletions(-)
diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index 08d01bc62c31..fd11f5c5d91e 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -261,7 +261,6 @@ prototypes::
int (*direct_IO)(struct kiocb *, struct iov_iter *iter);
int (*migrate_folio)(struct address_space *, struct folio *dst,
struct folio *src, enum migrate_mode);
- int (*launder_folio)(struct folio *);
bool (*is_partially_uptodate)(struct folio *, size_t from, size_t count);
int (*error_remove_folio)(struct address_space *, struct folio *);
int (*swap_activate)(struct swap_info_struct *sis, struct file *f, sector_t *span)
@@ -286,7 +285,6 @@ release_folio: yes
free_folio: yes
direct_IO:
migrate_folio: yes (both)
-launder_folio: yes
is_partially_uptodate: yes
error_remove_folio: yes
swap_activate: no
@@ -344,12 +342,6 @@ try_to_free_buffers().
->free_folio() is called when the kernel has dropped the folio
from the page cache.
-->launder_folio() may be called prior to releasing a folio if
-it is still found to be dirty. It returns zero if the folio was successfully
-cleaned, or an error value if not. Note that in order to prevent the folio
-getting mapped back in and redirtied, it needs to be kept locked
-across the entire operation.
-
->swap_activate() will be called to prepare the given file for swap. It
should perform any validation and preparation necessary to ensure that
writes can be performed with minimal memory allocation. It should call
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index 7c753148af88..bff64713bd09 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -768,7 +768,6 @@ cache in your filesystem. The following members are defined:
ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
int (*migrate_folio)(struct mapping *, struct folio *dst,
struct folio *src, enum migrate_mode);
- int (*launder_folio) (struct folio *);
bool (*is_partially_uptodate) (struct folio *, size_t from,
size_t count);
@@ -942,11 +941,6 @@ cache in your filesystem. The following members are defined:
folio to this function. migrate_folio should transfer any private
data across and update any references that it has to the folio.
-``launder_folio``
- Called before freeing a folio - it writes back the dirty folio.
- To prevent redirtying the folio, it is kept locked during the
- whole operation.
-
``is_partially_uptodate``
Called by the VM when reading a file through the pagecache when
the underlying blocksize is smaller than the size of the folio.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 50ce731a2b78..e0f4f518fe24 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -428,7 +428,6 @@ struct address_space_operations {
*/
int (*migrate_folio)(struct address_space *, struct folio *dst,
struct folio *src, enum migrate_mode);
- int (*launder_folio)(struct folio *);
bool (*is_partially_uptodate) (struct folio *, size_t from,
size_t count);
void (*is_dirty_writeback) (struct folio *, bool *dirty, bool *wb);
diff --git a/mm/truncate.c b/mm/truncate.c
index b58ba940be47..7f7d65fa926a 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -603,15 +603,6 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
}
EXPORT_SYMBOL(invalidate_mapping_pages);
-static int folio_launder(struct address_space *mapping, struct folio *folio)
-{
- if (!folio_test_dirty(folio))
- return 0;
- if (folio->mapping != mapping || mapping->a_ops->launder_folio == NULL)
- return 0;
- return mapping->a_ops->launder_folio(folio);
-}
-
/*
* This is like mapping_evict_folio(), except it ignores the folio's
* refcount. We do this because invalidate_inode_pages2() needs stronger
@@ -623,7 +614,6 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,
gfp_t gfp)
{
void (*free_folio)(struct folio *);
- int ret;
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
@@ -631,9 +621,8 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,
unmap_mapping_folio(folio);
BUG_ON(folio_mapped(folio));
- ret = folio_launder(mapping, folio);
- if (ret)
- return ret;
+ if (folio_test_dirty(folio))
+ return -EBUSY;
if (folio->mapping != mapping)
return -EBUSY;
if (!filemap_release_folio(folio, gfp))
--
2.47.3
prev parent reply other threads:[~2026-08-20 19:34 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 19:33 [PATCH 0/7] Remove aops->launder_folio Matthew Wilcox (Oracle)
2026-08-20 19:33 ` [PATCH 1/7] filemap: Export filemap_invalidate_pages() to modules Matthew Wilcox (Oracle)
2026-08-20 19:33 ` [PATCH 2/7] fuse: Use filemap_invalidate_pages() Matthew Wilcox (Oracle)
2026-08-20 20:37 ` Bernd Schubert
2026-08-24 9:05 ` Miklos Szeredi
2026-08-24 13:29 ` Matthew Wilcox
2026-08-24 13:49 ` Miklos Szeredi
2026-08-24 18:17 ` Matthew Wilcox
2026-08-24 19:33 ` Miklos Szeredi
2026-08-24 20:47 ` Matthew Wilcox
2026-08-25 7:08 ` Miklos Szeredi
2026-08-20 19:33 ` [PATCH 3/7] btrfs: " Matthew Wilcox (Oracle)
2026-08-24 21:57 ` Boris Burkov
2026-08-20 19:33 ` [PATCH 4/7] nfs: " Matthew Wilcox (Oracle)
2026-08-20 19:33 ` [PATCH 5/7] orangefs: " Matthew Wilcox (Oracle)
2026-08-20 19:33 ` [PATCH 6/7] orangefs: Remove launder_folio implementation Matthew Wilcox (Oracle)
2026-08-20 19:33 ` Matthew Wilcox (Oracle) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260820193343.3852967-8-willy@infradead.org \
--to=willy@infradead.org \
--cc=anna@kernel.org \
--cc=asml.silence@gmail.com \
--cc=brauner@kernel.org \
--cc=clm@fb.com \
--cc=devel@lists.orangefs.org \
--cc=dsterba@suse.com \
--cc=fuse-devel@lists.linux.dev \
--cc=hubcap@omnibond.com \
--cc=jack@suse.cz \
--cc=linux-block@vger.kernel.org \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-nfs@vger.kernel.org \
--cc=martin@omnibond.com \
--cc=miklos@szeredi.hu \
--cc=trondmy@kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox