diff options
| author | Christian Brauner <brauner@kernel.org> | 2026-07-22 15:42:18 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-07-31 12:28:47 +0200 |
| commit | fb770bb6fedffd1ce530e43d174518d2de3ea763 (patch) | |
| tree | 1ddd46139ee876ce93edee45e83d51efe2b8052b | |
| parent | 9dd2ac120e493ccd3ca554279c567fad149d6c5b (diff) | |
| parent | 881a27082e4d7faf21ad6960a3c6a0b6c5abc78d (diff) | |
Merge patch series "iomap/fuse: add helper to keep uptodate bitmap in sync"
Joanne Koong <joannelkoong@gmail.com> says:
iomap/fuse: add helper to keep uptodate bitmap in sync
Filesystems that use iomap normally mark folios uptodate through the iomap
read/write paths, which keep iomap's internal uptodate bitmap in sync.
However, some filesystems need to write data directly into the page cache
outside of those paths (eg fuse, which may need to write server-pushed data
straight into the page cache for servicing notify stores). These filesystems
need a way to mark a folio uptodate that also updates the iomap bitmap so
they're kept in sync.
This series adds iomap_folio_mark_uptodate() for filesystems to do that and
updates the relevant fuse call paths to use this. This is needed before fuse
can enable large folios.
Patch 1 ("fuse: don't clear folio uptodate on writethrough errors") was
originally submitted to the fuse tree [1] but patch 3 ("fuse: use iomap helper
to mark folio uptodate") has a dependency on it, so to make cross-coordination
between trees easier, patch 1 is now part of this series and submitted to the
vfs tree.
[1] https://lore.kernel.org/fuse-devel/20260624205201.842714-1-joannelkoong@gmail.com/
* patches from https://patch.msgid.link/20260707220450.1200943-1-joannelkoong@gmail.com:
fuse: use iomap helper to mark folio uptodate
iomap: add helper to mark folio uptodate
fuse: don't clear folio uptodate on writethrough errors
Link: https://patch.msgid.link/20260707220450.1200943-1-joannelkoong@gmail.com
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
| -rw-r--r-- | fs/fuse/file.c | 20 | ||||
| -rw-r--r-- | fs/fuse/notify.c | 4 | ||||
| -rw-r--r-- | fs/iomap/buffered-io.c | 6 | ||||
| -rw-r--r-- | include/linux/iomap.h | 1 |
4 files changed, 12 insertions, 19 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e052a0d44dee..ea4a15a7635a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1227,8 +1227,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia, struct file *file = iocb->ki_filp; struct fuse_file *ff = file->private_data; struct fuse_mount *fm = ff->fm; - unsigned int offset, i; - bool short_write; + unsigned int i; int err; for (i = 0; i < ap->num_folios; i++) @@ -1243,24 +1242,9 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia, if (!err && ia->write.out.size > count) err = -EIO; - short_write = ia->write.out.size < count; - offset = ap->descs[0].offset; - count = ia->write.out.size; for (i = 0; i < ap->num_folios; i++) { struct folio *folio = ap->folios[i]; - if (err) { - folio_clear_uptodate(folio); - } else { - if (count >= folio_size(folio) - offset) - count -= folio_size(folio) - offset; - else { - if (short_write) - folio_clear_uptodate(folio); - count = 0; - } - offset = 0; - } if (ia->write.folio_locked && (i == ap->num_folios - 1)) folio_unlock(folio); folio_put(folio); @@ -1335,7 +1319,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, /* If we copied full folio, mark it uptodate */ if (tmp == folio_size(folio)) - folio_mark_uptodate(folio); + iomap_folio_mark_uptodate(folio); if (folio_test_uptodate(folio)) { folio_unlock(folio); diff --git a/fs/fuse/notify.c b/fs/fuse/notify.c index 29578104ae6c..1ba763705d91 100644 --- a/fs/fuse/notify.c +++ b/fs/fuse/notify.c @@ -2,6 +2,8 @@ #include "dev.h" #include "fuse_i.h" + +#include <linux/iomap.h> #include <linux/pagemap.h> static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size, @@ -192,7 +194,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, if (!folio_test_uptodate(folio) && !err && folio_offset == 0 && (nr_bytes == folio_size(folio) || file_size == end)) { folio_zero_segment(folio, nr_bytes, folio_size(folio)); - folio_mark_uptodate(folio); + iomap_folio_mark_uptodate(folio); } folio_unlock(folio); folio_put(folio); diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 27bc2455a98d..f6040199d114 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -105,6 +105,12 @@ static void iomap_set_range_uptodate(struct folio *folio, size_t off, folio_mark_uptodate(folio); } +void iomap_folio_mark_uptodate(struct folio *folio) +{ + iomap_set_range_uptodate(folio, 0, folio_size(folio)); +} +EXPORT_SYMBOL_GPL(iomap_folio_mark_uptodate); + /* * Find the next dirty block in the folio. end_blk is inclusive. * If no dirty block is found, this will return end_blk + 1. diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 3582ed1fe236..21e73cb9c51e 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -365,6 +365,7 @@ struct folio *iomap_get_folio(struct iomap_iter *iter, loff_t pos, size_t len); bool iomap_release_folio(struct folio *folio, gfp_t gfp_flags); void iomap_invalidate_folio(struct folio *folio, size_t offset, size_t len); bool iomap_dirty_folio(struct address_space *mapping, struct folio *folio); +void iomap_folio_mark_uptodate(struct folio *folio); int iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len, const struct iomap_ops *ops, const struct iomap_write_ops *write_ops); |
