[PATCH 2/4] libfuse: set sync, immutable, and append when loading files

Darrick J. Wong
2025-09-16T00:47:15Z

Add these three fuse_attr::flags bits so that servers can mark a file as
immutable or append-only and have the kernel advertise and enforce that.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
include/fuse_common.h | 6 ++++++
include/fuse_kernel.h | 8 ++++++++
lib/fuse_lowlevel.c | 6 ++++++
3 files changed, 20 insertions(+)

diff --git a/include/fuse_common.h b/include/fuse_common.h
index eb08320bc8863f..9016721320eb5a 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -1236,6 +1236,12 @@ static inline bool fuse_iomap_need_write_allocate(unsigned int opflags,
#define FUSE_IFLAG_IOMAP (1U << 1)
/* enable untorn writes */
#define FUSE_IFLAG_ATOMIC (1U << 2)
+/* file writes are synchronous */
+#define FUSE_IFLAG_SYNC (1U << 3)
+/* file is immutable */
+#define FUSE_IFLAG_IMMUTABLE (1U << 4)
+/* file is append only */
+#define FUSE_IFLAG_APPEND (1U << 5)

/* Which fields are set in fuse_iomap_config_out? */
#define FUSE_IOMAP_CONFIG_SID (1 << 0ULL)
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index ed41792f94cf4f..4721c4e36159e1 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -242,6 +242,8 @@
* - add FUSE_IOMAP_CONFIG so the fuse server can configure more fs geometry
* - add FUSE_NOTIFY_IOMAP_DEV_INVAL to invalidate iomap bdev ranges
* - add FUSE_ATTR_ATOMIC for single-fsblock atomic write support
+ * - add FUSE_ATTR_{SYNC,IMMUTABLE,APPEND} for VFS enforcement of file
+ * attributes
*/

#ifndef _LINUX_FUSE_H
@@ -584,11 +586,17 @@ struct fuse_file_lock {
* FUSE_ATTR_DAX: Enable DAX for this file in per inode DAX mode
* FUSE_ATTR_IOMAP: Use iomap for this inode
* FUSE_ATTR_ATOMIC: Enable untorn writes
+ * FUSE_ATTR_SYNC: File writes are always synchronous
+ * FUSE_ATTR_IMMUTABLE: File is immutable
+ * FUSE_ATTR_APPEND: File is append-only
*/
#define FUSE_ATTR_SUBMOUNT (1 << 0)
#define FUSE_ATTR_DAX (1 << 1)
#define FUSE_ATTR_IOMAP (1 << 2)
#define FUSE_ATTR_ATOMIC (1 << 3)
+#define FUSE_ATTR_SYNC (1 << 4)
+#define FUSE_ATTR_IMMUTABLE (1 << 5)
+#define FUSE_ATTR_APPEND (1 << 6)

/**
* Open flags
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 6108b1862a7eb8..a6294c5c065cd2 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -128,6 +128,12 @@ static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr,
attr->flags |= FUSE_ATTR_IOMAP;
if (iflags & FUSE_IFLAG_ATOMIC)
attr->flags |= FUSE_ATTR_ATOMIC;
+ if (iflags & FUSE_IFLAG_SYNC)
+ attr->flags |= FUSE_ATTR_SYNC;
+ if (iflags & FUSE_IFLAG_IMMUTABLE)
+ attr->flags |= FUSE_ATTR_IMMUTABLE;
+ if (iflags & FUSE_IFLAG_APPEND)
+ attr->flags |= FUSE_ATTR_APPEND;
}

static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)