The branch main has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=6b8f0b47776bac6e4d2b7e4cfcecea485e4d91f9
commit 6b8f0b47776bac6e4d2b7e4cfcecea485e4d91f9 Author: Claudiu I. Palincas <msco...@protonmail.ch> AuthorDate: 2025-06-27 16:33:37 +0000 Commit: Alan Somers <asom...@freebsd.org> CommitDate: 2025-07-03 16:23:10 +0000 fusefs: Upgrade FUSE protocol to version 7.35. Upgrade the FUSE API from protocol 7.33 to 7.35. Add support for FOPEN_NOFLUSH, introduced in 7.35. Also, reduce diffs vis-a-vis upstream by factoring out an ioctl type, a change missed in d5e3cf41e89. Signed-off-by: Claudiu I. Palincas <msco...@protonmail.ch> Reviewed by: asomers Pull Request: https://github.com/freebsd/freebsd-src/pull/1744 --- sys/fs/fuse/fuse_file.h | 2 +- sys/fs/fuse/fuse_kernel.h | 18 ++++++++++++++++-- sys/fs/fuse/fuse_vnops.c | 4 ++++ tests/sys/fs/fusefs/flush.cc | 30 ++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/sys/fs/fuse/fuse_file.h b/sys/fs/fuse/fuse_file.h index 2a90e66d1b23..232132473953 100644 --- a/sys/fs/fuse/fuse_file.h +++ b/sys/fs/fuse/fuse_file.h @@ -139,7 +139,7 @@ struct fuse_filehandle { /* * flags returned by FUSE_OPEN - * Supported flags: FOPEN_DIRECT_IO, FOPEN_KEEP_CACHE + * Supported flags: FOPEN_DIRECT_IO, FOPEN_KEEP_CACHE, FOPEN_NOFLUSH * Unsupported: * FOPEN_NONSEEKABLE: Adding support would require a new per-file * or per-vnode attribute, which would have to be checked by diff --git a/sys/fs/fuse/fuse_kernel.h b/sys/fs/fuse/fuse_kernel.h index c95caf898ad8..942448b47365 100644 --- a/sys/fs/fuse/fuse_kernel.h +++ b/sys/fs/fuse/fuse_kernel.h @@ -182,6 +182,12 @@ * - add FUSE_OPEN_KILL_SUIDGID * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT * - add FUSE_SETXATTR_ACL_KILL_SGID + * + * 7.34 + * - add FUSE_SYNCFS + * + * 7.35 + * - add FOPEN_NOFLUSH */ #ifndef _FUSE_FUSE_KERNEL_H @@ -217,7 +223,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 33 +#define FUSE_KERNEL_MINOR_VERSION 35 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -288,12 +294,14 @@ struct fuse_file_lock { * FOPEN_NONSEEKABLE: the file is not seekable * FOPEN_CACHE_DIR: allow caching this directory * FOPEN_STREAM: the file is stream-like (no file position at all) + * FOPEN_NOFLUSH: don't flush data cache on close (unless FUSE_WRITEBACK_CACHE) */ #define FOPEN_DIRECT_IO (1 << 0) #define FOPEN_KEEP_CACHE (1 << 1) #define FOPEN_NONSEEKABLE (1 << 2) #define FOPEN_CACHE_DIR (1 << 3) #define FOPEN_STREAM (1 << 4) +#define FOPEN_NOFLUSH (1 << 5) /** * INIT request/reply flags @@ -518,6 +526,7 @@ enum fuse_opcode { FUSE_COPY_FILE_RANGE = 47, FUSE_SETUPMAPPING = 48, FUSE_REMOVEMAPPING = 49, + FUSE_SYNCFS = 50, #ifdef linux /* CUSE specific operations */ @@ -939,7 +948,8 @@ struct fuse_notify_retrieve_in { }; /* Device ioctls: */ -#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t) +#define FUSE_DEV_IOC_MAGIC 229 +#define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) struct fuse_lseek_in { uint64_t fh; @@ -992,4 +1002,8 @@ struct fuse_removemapping_one { #define FUSE_REMOVEMAPPING_MAX_ENTRY \ (PAGE_SIZE / sizeof(struct fuse_removemapping_one)) +struct fuse_syncfs_in { + uint64_t padding; +}; + #endif /* _FUSE_FUSE_KERNEL_H */ diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index 107e6db299e0..c0ec5a94b8d3 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -289,6 +289,10 @@ fuse_flush(struct vnode *vp, struct ucred *cred, pid_t pid, int fflag) if (err) return err; + if (fufh->fuse_open_flags & FOPEN_NOFLUSH && + (!fsess_opt_writeback(vnode_mount(vp)))) + return (0); + fdisp_init(&fdi, sizeof(*ffi)); fdisp_make_vp(&fdi, FUSE_FLUSH, vp, td, cred); ffi = fdi.indata; diff --git a/tests/sys/fs/fusefs/flush.cc b/tests/sys/fs/fusefs/flush.cc index 474cdbdb2203..7ba1218b3287 100644 --- a/tests/sys/fs/fusefs/flush.cc +++ b/tests/sys/fs/fusefs/flush.cc @@ -109,6 +109,36 @@ TEST_F(Flush, open_twice) EXPECT_EQ(0, close(fd)) << strerror(errno); } +/** + * Test for FOPEN_NOFLUSH: we expect that zero flush calls will be performed. + */ +TEST_F(Flush, open_noflush) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + uint64_t ino = 42; + uint64_t pid = (uint64_t)getpid(); + int fd; + + expect_lookup(RELPATH, ino, 1); + expect_open(ino, FOPEN_NOFLUSH, 1); + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in.header.opcode == FUSE_FLUSH && + in.header.nodeid == ino && + in.body.flush.lock_owner == pid && + in.body.flush.fh == FH); + }, Eq(true)), + _) + ).Times(0); + expect_release(); + + fd = open(FULLPATH, O_WRONLY); + ASSERT_LE(0, fd) << strerror(errno); + // close MUST not flush + EXPECT_EQ(0, close(fd)) << strerror(errno); +} + /* * Some FUSE filesystem cache data internally and flush it on release. Such * filesystems may generate errors during release. On Linux, these get