[PATCH 2/3] libfuse: add upper-level iomap cache management

Darrick J. Wong
2025-09-16T00:48:18Z

Make it so that upper-level fuse servers can use the iomap cache too.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
include/fuse.h | 31 +++++++++++++++++++++++++++++++
lib/fuse.c | 30 ++++++++++++++++++++++++++++++
lib/fuse_versionscript | 2 ++
3 files changed, 63 insertions(+)

diff --git a/include/fuse.h b/include/fuse.h
index 0b81a1259c4f09..baf7a2e90af5e7 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -1455,6 +1455,37 @@ bool fuse_fs_can_enable_iomap(const struct stat *statbuf);
*/
bool fuse_fs_can_enable_iomapx(const struct statx *statxbuf);

+/*
+ * Upsert some file mapping information into the kernel. This is necessary
+ * for filesystems that require coordination of mapping state changes between
+ * buffered writes and writeback, and desirable for better performance
+ * elsewhere.
+ *
+ * @param nodeid the inode number
+ * @param attr_ino inode number as told by fuse_attr::ino
+ * @param read mapping information for file reads
+ * @param write mapping information for file writes
+ * @return zero for success, -errno for failure
+ */
+int fuse_fs_iomap_upsert(uint64_t nodeid, uint64_t attr_ino,
+ const struct fuse_file_iomap *read,
+ const struct fuse_file_iomap *write);
+
+/**
+ * Invalidate some file mapping information in the kernel.
+ *
+ * @param nodeid the inode number
+ * @param attr_ino inode number as told by fuse_attr::ino
+ * @param read_off start of the range of read mappings to invalidate
+ * @param read_len length of the range of read mappings to invalidate
+ * @param write_off start of the range of write mappings to invalidate
+ * @param write_len length of the range of write mappings to invalidate
+ * @return zero for success, -errno for failure
+ */
+int fuse_fs_iomap_inval(uint64_t nodeid, uint64_t attr_ino, loff_t read_off,
+ uint64_t read_len, loff_t write_off,
+ uint64_t write_len);
+
int fuse_notify_poll(struct fuse_pollhandle *ph);

/**
diff --git a/lib/fuse.c b/lib/fuse.c
index ac0206f6ed4544..372363f0089284 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -2973,6 +2973,36 @@ static int fuse_fs_syncfs(struct fuse_fs *fs, const char *path)
return fs->op.syncfs(path);
}

+int fuse_fs_iomap_upsert(uint64_t nodeid, uint64_t attr_ino,
+ const struct fuse_file_iomap *read,
+ const struct fuse_file_iomap *write)
+{
+ struct fuse_context *ctxt = fuse_get_context();
+ struct fuse_session *se = fuse_get_session(ctxt->fuse);
+
+ return fuse_lowlevel_notify_iomap_upsert(se, nodeid, attr_ino,
+ read, write);
+}
+
+int fuse_fs_iomap_inval(uint64_t nodeid, uint64_t attr_ino, loff_t read_off,
+ uint64_t read_len, loff_t write_off,
+ uint64_t write_len)
+{
+ struct fuse_context *ctxt = fuse_get_context();
+ struct fuse_session *se = fuse_get_session(ctxt->fuse);
+ struct fuse_iomap_inval read = {
+ .offset = read_off,
+ .length = read_len,
+ };
+ struct fuse_iomap_inval write = {
+ .offset = write_off,
+ .length = write_len,
+ };
+
+ return fuse_lowlevel_notify_iomap_inval(se, nodeid, attr_ino, &read,
+ &write);
+}
+
static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int valid, struct fuse_file_info *fi)
{
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 48918d94d822e0..db95fc6e7b1b41 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -238,6 +238,8 @@ FUSE_3.99 {
fuse_fs_iomap_device_invalidate;
fuse_lowlevel_notify_iomap_upsert;
fuse_lowlevel_notify_iomap_inval;
+ fuse_fs_iomap_upsert;
+ fuse_fs_iomap_inval;
} FUSE_3.18;