[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <176169814940.1428772.13665592936257476002.stgit@frogsfrogsfrogs>
Date: Tue, 28 Oct 2025 18:08:25 -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 5/5] fuservicemount: create loop devices for regular files
From: Darrick J. Wong <djwong@...nel.org>
If a fuse server asks fuservicemount to open a regular file, try to
create an auto-clear loop device so that the fuse server can use iomap.
Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>
---
include/fuse_service.h | 6 ++++++
include/fuse_service_priv.h | 3 ++-
lib/fuse_service.c | 5 ++++-
util/mount_service.c | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/include/fuse_service.h b/include/fuse_service.h
index 47080a75bc9ab6..906f36434d2243 100644
--- a/include/fuse_service.h
+++ b/include/fuse_service.h
@@ -95,6 +95,12 @@ int fuse_service_take_fusedev(struct fuse_service *sfp);
int fuse_service_parse_cmdline_opts(struct fuse_args *args,
struct fuse_cmdline_opts *opts);
+/**
+ * If the file opened is a regular file, try to create a loop device for it.
+ * If successful, the loop device is returned; if not, the regular file is.
+ */
+#define FUSE_SERVICE_REQUEST_FILE_TRYLOOP (1U << 0)
+
/**
* Ask the mount.service helper to open a file on behalf of the fuse server.
*
diff --git a/include/fuse_service_priv.h b/include/fuse_service_priv.h
index ce2e194ccf0be6..6fc7d59c363ea8 100644
--- a/include/fuse_service_priv.h
+++ b/include/fuse_service_priv.h
@@ -58,7 +58,8 @@ static inline size_t sizeof_fuse_service_requested_file(size_t pathlen)
return sizeof(struct fuse_service_requested_file) + pathlen + 1;
}
-#define FUSE_SERVICE_OPEN_FLAGS (0)
+#define FUSE_SERVICE_OPEN_TRYLOOP (1U << 0)
+#define FUSE_SERVICE_OPEN_FLAGS (FUSE_SERVICE_OPEN_TRYLOOP)
struct fuse_service_open_command {
struct fuse_service_packet p;
diff --git a/lib/fuse_service.c b/lib/fuse_service.c
index 48633640c1c41b..af23ec06ac60a1 100644
--- a/lib/fuse_service.c
+++ b/lib/fuse_service.c
@@ -152,7 +152,7 @@ int fuse_service_receive_file(struct fuse_service *sf, const char *path,
return recv_requested_file(sf->sockfd, path, fdp);
}
-#define FUSE_SERVICE_REQUEST_FILE_FLAGS (0)
+#define FUSE_SERVICE_REQUEST_FILE_FLAGS (FUSE_SERVICE_REQUEST_FILE_TRYLOOP)
int fuse_service_request_file(struct fuse_service *sf, const char *path,
int open_flags, mode_t create_mode,
@@ -177,6 +177,9 @@ int fuse_service_request_file(struct fuse_service *sf, const char *path,
return -1;
}
+ if (request_flags & FUSE_SERVICE_REQUEST_FILE_TRYLOOP)
+ rqflags |= FUSE_SERVICE_OPEN_TRYLOOP;
+
cmd = calloc(1, iov.iov_len);
if (!cmd) {
perror("fuse: alloc service file request");
diff --git a/util/mount_service.c b/util/mount_service.c
index e3410d524167a4..e62183800043e8 100644
--- a/util/mount_service.c
+++ b/util/mount_service.c
@@ -25,15 +25,20 @@
#include <limits.h>
#include <sys/stat.h>
#include <arpa/inet.h>
+#ifdef HAVE_STRUCT_LOOP_CONFIG_INFO
+# include <linux/loop.h>
+#endif
#include "mount_util.h"
#include "util.h"
#include "fuse_i.h"
#include "fuse_service_priv.h"
+#include "fuse_loopdev.h"
#include "mount_service.h"
#define FUSE_KERN_DEVICE_ENV "FUSE_KERN_DEVICE"
#define FUSE_DEV "/dev/fuse"
+#define LOOPCTL "/dev/loop-control"
struct mount_service {
/* alleged fuse subtype based on -t cli argument */
@@ -542,6 +547,35 @@ static int mount_service_handle_open_cmd(struct mount_service *mo,
return mount_service_send_file_error(mo, error, oc->path);
}
+ if (request_flags & FUSE_SERVICE_OPEN_TRYLOOP) {
+ int loop_fd = -1;
+
+ ret = fuse_loopdev_setup(fd, ntohl(oc->open_flags), oc->path,
+ 5, &loop_fd, NULL);
+ if (ret) {
+ /*
+ * If the setup function returned EBUSY, there is
+ * already a loop device backed by this file, so we
+ * must return an error. For any other type of error
+ * we'll send back the first file we opened.
+ */
+ if (errno == EBUSY) {
+ ret = mount_service_send_file_error(mo, errno,
+ oc->path);
+ close(fd);
+ return ret;
+ }
+ } else if (loop_fd >= 0) {
+ /*
+ * Send back the loop device instead of the file.
+ */
+ ret = mount_service_send_file(mo, oc->path, loop_fd);
+ close(loop_fd);
+ close(fd);
+ return ret;
+ }
+ }
+
ret = mount_service_send_file(mo, oc->path, fd);
close(fd);
return ret;
Powered by blists - more mailing lists