[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <176169813912.1427432.13731634577241744688.stgit@frogsfrogsfrogs>
Date: Tue, 28 Oct 2025 18:04:46 -0700
From: "Darrick J. Wong" <djwong@...nel.org>
To: djwong@...nel.org, bschubert@....com
Cc: linux-ext4@...r.kernel.org, linux-fsdevel@...r.kernel.org,
bernd@...ernd.com, miklos@...redi.hu, joannelkoong@...il.com, neal@...pa.dev
Subject: [PATCH 21/22] libfuse: add lower-level filesystem freeze, thaw,
and shutdown requests
From: Darrick J. Wong <djwong@...nel.org>
Pass the kernel's filesystem freeze, thaw, and shutdown requests through
to low level fuse servers.
Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>
---
include/fuse_kernel.h | 12 +++++++++
include/fuse_lowlevel.h | 35 +++++++++++++++++++++++++++
lib/fuse_lowlevel.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 107 insertions(+)
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index 5b9259714a628d..37e5eb8c65f206 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -676,6 +676,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,
@@ -1225,6 +1229,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/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index 110f7f73edbb2a..b37d1f03ab5d7f 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -1422,6 +1422,41 @@ struct fuse_lowlevel_ops {
*/
void (*iomap_config) (fuse_req_t req, uint64_t flags,
uint64_t maxbytes);
+
+ /**
+ * Freeze the filesystem
+ *
+ * Valid replies:
+ * fuse_reply_err
+ *
+ * @param req request handle
+ * @param ino the root inode number
+ * @param unlinked count of open unlinked inodes
+ */
+ void (*freezefs) (fuse_req_t req, fuse_ino_t ino, uint64_t unlinked);
+
+ /**
+ * Thaw the filesystem
+ *
+ * Valid replies:
+ * fuse_reply_err
+ *
+ * @param req request handle
+ * @param ino the root inode number
+ */
+ void (*unfreezefs) (fuse_req_t req, fuse_ino_t ino);
+
+ /**
+ * Shut down the filesystem
+ *
+ * Valid replies:
+ * fuse_reply_err
+ *
+ * @param req request handle
+ * @param ino the root inode number
+ * @param flags zero, currently
+ */
+ void (*shutdownfs) (fuse_req_t req, fuse_ino_t ino, uint64_t flags);
};
/**
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 605848bb4cd55b..728a6b635471c7 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -2835,6 +2835,60 @@ static void do_iomap_config(fuse_req_t req, const fuse_ino_t nodeid,
_do_iomap_config(req, nodeid, inarg, NULL);
}
+static void _do_freezefs(fuse_req_t req, const fuse_ino_t nodeid,
+ const void *op_in, const void *in_payload)
+{
+ const struct fuse_freezefs_in *inarg = op_in;
+ (void)in_payload;
+
+ if (req->se->op.freezefs)
+ req->se->op.freezefs(req, nodeid, inarg->unlinked);
+ else
+ fuse_reply_err(req, ENOSYS);
+}
+
+static void do_freezefs(fuse_req_t req, const fuse_ino_t nodeid,
+ const void *inarg)
+{
+ _do_freezefs(req, nodeid, inarg, NULL);
+}
+
+static void _do_unfreezefs(fuse_req_t req, const fuse_ino_t nodeid,
+ const void *op_in, const void *in_payload)
+{
+ (void)op_in;
+ (void)in_payload;
+
+ if (req->se->op.unfreezefs)
+ req->se->op.unfreezefs(req, nodeid);
+ else
+ fuse_reply_err(req, ENOSYS);
+}
+
+static void do_unfreezefs(fuse_req_t req, const fuse_ino_t nodeid,
+ const void *inarg)
+{
+ _do_unfreezefs(req, nodeid, inarg, NULL);
+}
+
+static void _do_shutdownfs(fuse_req_t req, const fuse_ino_t nodeid,
+ const void *op_in, const void *in_payload)
+{
+ const struct fuse_shutdownfs_in *inarg = op_in;
+ (void)in_payload;
+
+ if (req->se->op.shutdownfs)
+ req->se->op.shutdownfs(req, nodeid, inarg->flags);
+ else
+ fuse_reply_err(req, ENOSYS);
+}
+
+static void do_shutdownfs(fuse_req_t req, const fuse_ino_t nodeid,
+ const void *inarg)
+{
+ _do_shutdownfs(req, nodeid, inarg, NULL);
+}
+
static bool want_flags_valid(uint64_t capable, uint64_t want)
{
uint64_t unknown_flags = want & (~capable);
@@ -3764,6 +3818,9 @@ static struct {
[FUSE_COPY_FILE_RANGE_64] = { do_copy_file_range_64, "COPY_FILE_RANGE_64" },
[FUSE_LSEEK] = { do_lseek, "LSEEK" },
[FUSE_STATX] = { do_statx, "STATX" },
+ [FUSE_FREEZE_FS] = { do_freezefs, "FREEZE" },
+ [FUSE_UNFREEZE_FS] = { do_unfreezefs, "UNFREEZE" },
+ [FUSE_SHUTDOWN_FS] = { do_shutdownfs, "SHUTDOWN" },
[FUSE_IOMAP_CONFIG]= { do_iomap_config, "IOMAP_CONFIG" },
[FUSE_IOMAP_BEGIN] = { do_iomap_begin, "IOMAP_BEGIN" },
[FUSE_IOMAP_END] = { do_iomap_end, "IOMAP_END" },
@@ -3824,6 +3881,9 @@ static struct {
[FUSE_COPY_FILE_RANGE_64] = { _do_copy_file_range_64, "COPY_FILE_RANGE_64" },
[FUSE_LSEEK] = { _do_lseek, "LSEEK" },
[FUSE_STATX] = { _do_statx, "STATX" },
+ [FUSE_FREEZE_FS] = { _do_freezefs, "FREEZE" },
+ [FUSE_UNFREEZE_FS] = { _do_unfreezefs, "UNFREEZE" },
+ [FUSE_SHUTDOWN_FS] = { _do_shutdownfs, "SHUTDOWN" },
[FUSE_IOMAP_CONFIG] = { _do_iomap_config, "IOMAP_CONFIG" },
[FUSE_IOMAP_BEGIN] = { _do_iomap_begin, "IOMAP_BEGIN" },
[FUSE_IOMAP_END] = { _do_iomap_end, "IOMAP_END" },
Powered by blists - more mailing lists