[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <176169811023.1424854.7225516717354931327.stgit@frogsfrogsfrogs>
Date: Tue, 28 Oct 2025 17:53:02 -0700
From: "Darrick J. Wong" <djwong@...nel.org>
To: djwong@...nel.org, miklos@...redi.hu
Cc: joannelkoong@...il.com, bernd@...ernd.com, neal@...pa.dev,
linux-ext4@...r.kernel.org, linux-fsdevel@...r.kernel.org
Subject: [PATCH 31/31] fuse: implement freeze and shutdowns for iomap
filesystems
From: Darrick J. Wong <djwong@...nel.org>
Implement filesystem freezing and block device shutdown notifications
for iomap-based servers
Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>
---
include/uapi/linux/fuse.h | 12 +++++++
fs/fuse/inode.c | 73 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 41e88f1089f1b9..5d10e471f2df7f 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -690,6 +690,10 @@ enum fuse_opcode {
FUSE_STATX = 52,
FUSE_COPY_FILE_RANGE_64 = 53,
+ FUSE_FREEZE_FS = 4089,
+ FUSE_UNFREEZE_FS = 4090,
+ FUSE_SHUTDOWN_FS = 4091,
+
FUSE_IOMAP_CONFIG = 4092,
FUSE_IOMAP_IOEND = 4093,
FUSE_IOMAP_BEGIN = 4094,
@@ -1251,6 +1255,14 @@ struct fuse_syncfs_in {
uint64_t padding;
};
+struct fuse_freezefs_in {
+ uint64_t unlinked;
+};
+
+struct fuse_shutdownfs_in {
+ uint64_t flags;
+};
+
/*
* For each security context, send fuse_secctx with size of security context
* fuse_secctx will be followed by security context name and this in turn
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index c3f985baf21c77..d41a6e418537b5 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1221,6 +1221,74 @@ static struct dentry *fuse_get_parent(struct dentry *child)
return parent;
}
+#ifdef CONFIG_FUSE_IOMAP
+/*
+ * Second stage of a freeze. The data is already frozen so we only
+ * need to take care of the fuse server.
+ */
+static int fuse_freeze_fs(struct super_block *sb)
+{
+ struct fuse_mount *fm = get_fuse_mount_super(sb);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ struct fuse_freezefs_in inarg = {
+ .unlinked = atomic_long_read(&sb->s_remove_count),
+ };
+ FUSE_ARGS(args);
+ int err;
+
+ if (!fc->iomap)
+ return -EOPNOTSUPP;
+
+ args.opcode = FUSE_FREEZE_FS;
+ args.nodeid = get_node_id(sb->s_root->d_inode);
+ args.in_numargs = 1;
+ args.in_args[0].size = sizeof(inarg);
+ args.in_args[0].value = &inarg;
+ err = fuse_simple_request(fm, &args);
+ if (err == -ENOSYS)
+ err = -EOPNOTSUPP;
+ return err;
+}
+
+static int fuse_unfreeze_fs(struct super_block *sb)
+{
+ struct fuse_mount *fm = get_fuse_mount_super(sb);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ FUSE_ARGS(args);
+ int err;
+
+ if (!fc->iomap)
+ return 0;
+
+ args.opcode = FUSE_UNFREEZE_FS;
+ args.nodeid = get_node_id(sb->s_root->d_inode);
+ err = fuse_simple_request(fm, &args);
+ if (err == -ENOSYS)
+ err = 0;
+ return err;
+}
+
+static void fuse_shutdown_fs(struct super_block *sb)
+{
+ struct fuse_mount *fm = get_fuse_mount_super(sb);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ struct fuse_shutdownfs_in inarg = {
+ .flags = 0,
+ };
+ FUSE_ARGS(args);
+
+ if (!fc->iomap)
+ return;
+
+ args.opcode = FUSE_SHUTDOWN_FS;
+ args.nodeid = get_node_id(sb->s_root->d_inode);
+ args.in_numargs = 1;
+ args.in_args[0].size = sizeof(inarg);
+ args.in_args[0].value = &inarg;
+ fuse_simple_request(fm, &args);
+}
+#endif /* CONFIG_FUSE_IOMAP */
+
/* only for fid encoding; no support for file handle */
static const struct export_operations fuse_export_fid_operations = {
.encode_fh = fuse_encode_fh,
@@ -1243,6 +1311,11 @@ static const struct super_operations fuse_super_operations = {
.statfs = fuse_statfs,
.sync_fs = fuse_sync_fs,
.show_options = fuse_show_options,
+#ifdef CONFIG_FUSE_IOMAP
+ .freeze_fs = fuse_freeze_fs,
+ .unfreeze_fs = fuse_unfreeze_fs,
+ .shutdown = fuse_shutdown_fs,
+#endif
};
static void sanitize_global_limit(unsigned int *limit)
Powered by blists - more mailing lists