All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	linux-ext4 <linux-ext4@vger.kernel.org>,
	fuse-devel <fuse-devel@lists.linux.dev>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
	Bernd Schubert <bernd@bsbernd.com>,
	Joanne Koong <joannelkoong@gmail.com>,
	Theodore Ts'o <tytso@mit.edu>, Neal Gompa <neal@gompa.dev>,
	Amir Goldstein <amir73il@gmail.com>,
	Christian Brauner <brauner@kernel.org>,
	demiobenour@gmail.com
Subject: [RFC PATCH 2/4] exfat: enable fuse systemd service mode
Date: Wed, 22 Apr 2026 16:30:45 -0700	[thread overview]
Message-ID: <20260422233045.GH7739@frogsfrogsfrogs> (raw)
In-Reply-To: <20260422231518.GA7717@frogsfrogsfrogs>

From: Darrick J. Wong <djwong@kernel.org>

Enable use of exfat as a contained systemd service.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
 libexfat/exfat.h       |    3 +
 configure.ac           |  150 ++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/Makefile.am       |   16 +++++
 fuse/exfat.socket.in   |   15 +++++
 fuse/exfat@.service.in |  102 +++++++++++++++++++++++++++++++++
 fuse/main.c            |  131 ++++++++++++++++++++++++++++++++++++++++--
 libexfat/io.c          |   21 ++++++-
 libexfat/mount.c       |   19 +++++-
 8 files changed, 447 insertions(+), 10 deletions(-)
 create mode 100644 fuse/exfat.socket.in
 create mode 100644 fuse/exfat@.service.in

diff --git a/libexfat/exfat.h b/libexfat/exfat.h
index 9b9a682844c093..3023ecd53acd5b 100644
--- a/libexfat/exfat.h
+++ b/libexfat/exfat.h
@@ -147,6 +147,7 @@ void exfat_warn(const char* format, ...) PRINTF;
 void exfat_debug(const char* format, ...) PRINTF;
 
 struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode);
+struct exfat_dev* exfat_fdopen(int fd, const char* spec, enum exfat_mode mode);
 int exfat_close(struct exfat_dev* dev);
 int exfat_fsync(struct exfat_dev* dev);
 enum exfat_mode exfat_get_mode(const struct exfat_dev* dev);
@@ -225,6 +226,8 @@ int exfat_set_label(struct exfat* ef, const char* label);
 
 int exfat_soil_super_block(const struct exfat* ef);
 int exfat_mount(struct exfat* ef, const char* spec, const char* options);
+int exfat_mount_from(struct exfat* ef, int fd, const char* spec,
+		     const char* options);
 void exfat_unmount(struct exfat* ef);
 
 time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec,
diff --git a/configure.ac b/configure.ac
index ee62b88931b738..63e7327f7ee651 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,7 +32,7 @@ AM_PROG_AR
 AC_SYS_LARGEFILE
 AC_CANONICAL_HOST
 PKG_CHECK_MODULES([FUSE3], [fuse3],
-  [AC_DEFINE([FUSE_USE_VERSION], [30], [Required FUSE API version.])],
+  [have_fuse3_pkg=yes ; AC_DEFINE([FUSE_USE_VERSION], [319], [Required FUSE API version.])],
   [PKG_CHECK_MODULES([FUSE2], [fuse >= 2.6],
     [AC_DEFINE([FUSE_USE_VERSION], [26], [Required FUSE API version.])])])
 AC_MSG_CHECKING([whether host-specific configuration is needed for $host_os])
@@ -55,6 +55,154 @@ case "$host_os" in
     AC_MSG_RESULT([no])
 	;;
 esac
+
+
+dnl
+dnl Check if the FUSE library tells us where to put fs service sockets
+dnl
+have_fuse_service=
+fuse_service_socket_dir=
+if test -n "$have_fuse3_pkg"
+then
+	AC_ARG_WITH([fuse_service_socket_dir],
+	  [AS_HELP_STRING([--with-fuse-service-socket-dir@<:@=DIR@:>@],
+		  [Create fuse3 filesystem service sockets in DIR.])],
+	  [],
+	  [with_fuse_service_socket_dir=yes])
+	AS_IF([test "x${with_fuse_service_socket_dir}" != "xno"],
+	  [
+		AS_IF([test "x${with_fuse_service_socket_dir}" = "xyes"],
+		  [
+			AS_IF([test "x$have_fuse3_pkg" = "xyes" ],
+			  [
+				with_fuse_service_socket_dir="$($PKG_CONFIG --variable=service_socket_dir fuse3)"
+			  ], [
+				with_fuse_service_socket_dir=""
+			  ])
+		  ])
+		AC_MSG_CHECKING([for fuse3 service socket dir])
+		fuse_service_socket_dir="${with_fuse_service_socket_dir}"
+		AS_IF([test -n "${fuse_service_socket_dir}"],
+		  [
+			AC_MSG_RESULT(${fuse_service_socket_dir})
+		  ],
+		  [
+			AC_MSG_RESULT(no)
+		  ])
+	  ],
+	  [])
+	AC_ARG_WITH([fuse_service_socket_perms],
+	  [AS_HELP_STRING([--with-fuse-service-socket-perms@<:@=MODE@:>@],
+		  [Create fuse3 filesystem service socket with these permissions.])],
+	  [],
+	  [with_fuse_service_socket_perms=yes])
+	AS_IF([test "x${with_fuse_service_socket_perms}" != "xno"],
+	  [
+		AS_IF([test "x${with_fuse_service_socket_perms}" = "xyes"],
+		  [
+			AS_IF([test "x$have_fuse3_pkg" = "xyes" ],
+			  [
+				with_fuse_service_socket_perms="$($PKG_CONFIG --variable=service_socket_perms fuse3)"
+			  ], [
+				with_fuse_service_socket_perms=""
+			  ])
+		  ])
+		fuse_service_socket_perms="${with_fuse_service_socket_perms}"
+	  ],
+	  [])
+
+	AC_MSG_CHECKING([for fuse_service_accept in libfuse])
+	old_cflags="$CFLAGS"
+	CFLAGS="$CFLAGS $FUSE3_CFLAGS"
+	AC_LINK_IFELSE(
+	[	AC_LANG_PROGRAM([[
+	#define _GNU_SOURCE
+	#define _FILE_OFFSET_BITS	64
+	#define FUSE_USE_VERSION	319
+	#include <fuse_lowlevel.h>
+	#include <fuse_service.h>
+		]], [[
+	struct fuse_service *moo;
+	fuse_service_accepted(moo);
+		]])
+	], have_fuse_service_accept=yes
+	   AC_MSG_RESULT(yes),
+	   AC_MSG_RESULT(no))
+	CFLAGS="$old_cflags"
+
+	AC_MSG_CHECKING([for fuse3 service support])
+	AS_IF([test -n "${fuse_service_socket_dir}" && test "${have_fuse_service_accept}" = "yes"],
+	  [
+		AC_MSG_RESULT(yes)
+		have_fuse_service="yes"
+	  ],
+	  [
+		AC_MSG_RESULT(no)
+	  ])
+fi
+AC_SUBST(have_fuse_service)
+AC_SUBST(fuse_service_socket_dir)
+AC_SUBST(fuse_service_socket_perms)
+if test "$have_fuse_service" = yes
+then
+	AC_DEFINE(HAVE_FUSE_SERVICE, 1, [Define to 1 if fuse supports service])
+fi
+
+dnl
+dnl Where do systemd services go?
+dnl
+AC_ARG_WITH([systemd_unit_dir],
+  [AS_HELP_STRING([--with-systemd-unit-dir@<:@=DIR@:>@],
+	[Install systemd system units into DIR.])],
+  [],
+  [with_systemd_unit_dir=yes])
+AS_IF([test "x${with_systemd_unit_dir}" != "xno"],
+  [
+	AS_IF([test "x${with_systemd_unit_dir}" = "xyes"],
+	  [
+		PKG_CHECK_MODULES([systemd], [systemd],
+		  [
+			with_systemd_unit_dir="$($PKG_CONFIG --variable=systemdsystemunitdir systemd)"
+		  ], [
+			with_systemd_unit_dir=""
+		  ])
+		m4_pattern_allow([^PKG_(MAJOR|MINOR|BUILD|REVISION)$])
+	  ])
+	AC_MSG_CHECKING([for systemd system unit dir])
+	systemd_system_unit_dir="${with_systemd_unit_dir}"
+	AS_IF([test -n "${systemd_system_unit_dir}"],
+	  [
+		AC_MSG_RESULT(${systemd_system_unit_dir})
+		have_systemd="yes"
+	  ],
+	  [
+		AC_MSG_RESULT(no)
+		have_systemd="no"
+	  ])
+  ],
+  [
+	have_systemd="disabled"
+  ])
+AC_SUBST(have_systemd)
+AC_SUBST(systemd_system_unit_dir)
+
+AC_MSG_CHECKING([for exfat-fuse service support and systemd])
+AS_IF([test "${FUSE4FS_CMT}${have_fuse_service}${have_systemd}" = "yesyes"],
+      [
+           AC_MSG_RESULT(yes)
+           AC_DEFINE(HAVE_EXFAT_FUSE_SERVICE, 1,
+                     [Define to 1 if exfat should be built with fuse service support])
+           have_exfat_service=yes
+           AM_CONDITIONAL(HAVE_EXFAT_FUSE_SERVICE, [true])
+      ],
+      [
+           AC_MSG_RESULT(no)
+           AM_CONDITIONAL(HAVE_EXFAT_FUSE_SERVICE, [false])
+           have_exfat_service=no
+      ]
+)
+AC_SUBST(have_exfat_service)
+
 AC_CONFIG_HEADERS([libexfat/config.h])
 AC_CONFIG_FILES([
 	libexfat/Makefile
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index 09c8cac9f5d0ec..660b23ce1965fc 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -27,6 +27,22 @@ mount_exfat_fuse_CPPFLAGS = -imacros $(top_srcdir)/libexfat/config.h
 mount_exfat_fuse_CFLAGS = $(FUSE2_CFLAGS) $(FUSE3_CFLAGS) $(UBLIO_CFLAGS)
 mount_exfat_fuse_LDADD = $(top_srcdir)/libexfat/libexfat.a $(FUSE2_LIBS) $(FUSE3_LIBS) $(UBLIO_LIBS)
 
+if HAVE_EXFAT_FUSE_SERVICE
+bin_SCRIPTS = exfat.socket exfat@.service
+endif
+
+exfat.socket: exfat.socket.in
+	sed \
+		-e "s|@FUSE3_SERVICE_SOCKET_DIR@|$(fuse_service_socket_dir)|g" \
+		-e "s|@FUSE3_SERVICE_SOCKET_PERMS@|$(fuse_service_socket_perms)|g" \
+		< $< > $@
+
+exfat@.service: exfat@.service.in
+	sed -e "s|@SBINDIR@|$(sbindir)|g" \
+		   < $< > $@
+
+EXTRA_PROGRAMS=$(SERVICE_FILES)
+
 install-exec-hook:
 	ln -sf $(sbin_PROGRAMS) $(DESTDIR)$(sbindir)/mount.exfat
 
diff --git a/fuse/exfat.socket.in b/fuse/exfat.socket.in
new file mode 100644
index 00000000000000..8a957ad700fc16
--- /dev/null
+++ b/fuse/exfat.socket.in
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2026 Oracle.  All Rights Reserved.
+# Author: Darrick J. Wong <djwong@kernel.org>
+[Unit]
+Description=Socket for exfat Service
+
+[Socket]
+ListenSequentialPacket=@FUSE3_SERVICE_SOCKET_DIR@/exfat
+Accept=yes
+SocketMode=@FUSE3_SERVICE_SOCKET_PERMS@
+RemoveOnStop=yes
+
+[Install]
+WantedBy=sockets.target
diff --git a/fuse/exfat@.service.in b/fuse/exfat@.service.in
new file mode 100644
index 00000000000000..9b7855fe524de6
--- /dev/null
+++ b/fuse/exfat@.service.in
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2026 Oracle.  All Rights Reserved.
+# Author: Darrick J. Wong <djwong@kernel.org>
+[Unit]
+Description=exfat Service
+
+# Don't leave failed units behind, systemd does not clean them up!
+CollectMode=inactive-or-failed
+
+[Service]
+Type=exec
+ExecStart=/@SBINDIR@/mount.exfat-fuse
+
+# Try to capture core dumps
+LimitCORE=infinity
+
+SyslogIdentifier=%N
+
+# No realtime CPU scheduling
+RestrictRealtime=true
+
+# Don't let us see anything in the regular system, and don't run as root
+DynamicUser=true
+ProtectSystem=strict
+ProtectHome=true
+PrivateTmp=true
+PrivateDevices=true
+PrivateUsers=true
+
+# No network access
+PrivateNetwork=true
+ProtectHostname=true
+RestrictAddressFamilies=none
+IPAddressDeny=any
+
+# Don't let the program mess with the kernel configuration at all
+ProtectKernelLogs=true
+ProtectKernelModules=true
+ProtectKernelTunables=true
+ProtectControlGroups=true
+ProtectProc=invisible
+RestrictNamespaces=true
+RestrictFileSystems=
+
+# Hide everything in /proc, even /proc/mounts
+ProcSubset=pid
+
+# Only allow the default personality Linux
+LockPersonality=true
+
+# No writable memory pages
+MemoryDenyWriteExecute=true
+
+# Don't let our mounts leak out to the host
+PrivateMounts=true
+
+# Restrict system calls to the native arch and only enough to get things going
+SystemCallArchitectures=native
+SystemCallFilter=@system-service
+SystemCallFilter=~@privileged
+SystemCallFilter=~@resources
+
+SystemCallFilter=~@clock
+SystemCallFilter=~@cpu-emulation
+SystemCallFilter=~@debug
+SystemCallFilter=~@module
+SystemCallFilter=~@reboot
+SystemCallFilter=~@swap
+
+SystemCallFilter=~@mount
+
+# libfuse io_uring wants to pin cores and memory
+SystemCallFilter=mbind
+SystemCallFilter=sched_setaffinity
+
+# Leave a breadcrumb if we get whacked by the system call filter
+SystemCallErrorNumber=EL3RST
+
+# Log to the kernel dmesg, just like an in-kernel ext4 driver
+StandardOutput=append:/dev/ttyprintk
+StandardError=append:/dev/ttyprintk
+
+# Run with no capabilities at all
+CapabilityBoundingSet=
+AmbientCapabilities=
+NoNewPrivileges=true
+
+# fuse4fs doesn't create files
+UMask=7777
+
+# No access to hardware /dev files at all
+ProtectClock=true
+DevicePolicy=closed
+
+# Don't mess with set[ug]id anything.
+RestrictSUIDSGID=true
+
+# Don't let OOM kills of processes in this containment group kill the whole
+# service, because we don't want filesystem drivers to go down.
+OOMPolicy=continue
+OOMScoreAdjust=-1000
diff --git a/fuse/main.c b/fuse/main.c
index cf1033a543f038..d7aa8d21db62e3 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -34,6 +34,10 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <unistd.h>
+#ifdef HAVE_EXFAT_FUSE_SERVICE
+# include <sys/mount.h>
+# include <fuse_service.h>
+#endif
 
 #ifndef DEBUG
 	#define exfat_debug(format, ...) do {} while (0)
@@ -45,6 +49,102 @@
 
 struct exfat ef;
 
+#ifdef HAVE_EXFAT_FUSE_SERVICE
+static struct fuse_service *service;
+static int bdev_fd = -1;
+
+static inline bool fuse_exfat_is_service(void)
+{
+	return fuse_service_accepted(service);
+}
+
+static int fuse_exfat_service_connect(struct fuse_args *args)
+{
+	int ret;
+
+	ret = fuse_service_accept(&service);
+	if (ret)
+		return ret;
+
+	if (fuse_service_accepted(service))
+		return fuse_service_append_args(service, args);
+
+	return 0;
+}
+
+static int fuse_exfat_service_get_config(const char *device, bool ro)
+{
+	int open_flags = 0; /* fuseblk server means we can't open exclusive */
+	int fd;
+	int ret;
+
+	if (ro)
+		open_flags |= O_RDONLY;
+	else
+		open_flags |= O_SYNC | O_RDWR;
+
+	ret = fuse_service_request_file(service, device, open_flags, 0, 0);
+	if (ret)
+		return ret;
+
+	ret = fuse_service_receive_file(service, device, &fd);
+	if (ret)
+		return ret;
+
+	if (fd < 0) {
+		fprintf(stderr, "%s opening device: %s.\n", device,
+			   strerror(-fd));
+		return -1;
+	}
+	bdev_fd = fd;
+
+	return fuse_service_finish_file_requests(service);
+}
+
+static int fuse_exfat_service_mount(struct exfat *ef, const char *spec,
+				    const char *exfat_options)
+{
+	const int is_ro = exfat_match_option(exfat_options, "ro");
+	int rc;
+
+	rc = fuse_exfat_service_get_config(spec, is_ro);
+	if (rc)
+		return EXIT_FAILURE;
+
+	return exfat_mount_from(ef, bdev_fd, spec, exfat_options);
+}
+
+static int fuse_exfat_service_main(char **argv,
+				   const struct fuse_operations *ops)
+{
+	struct fuse_args args = FUSE_ARGS_INIT(0, argv);
+	char **p = argv;
+
+	while (*(p++) != NULL)
+		args.argc++;
+
+	fuse_service_expect_mount_format(service, S_IFDIR);
+	return fuse_service_main(service, &args, ops, NULL);
+}
+
+static int fuse_exfat_service_finish(int exitcode)
+{
+	if (!fuse_exfat_is_service())
+		return exitcode;
+
+	fuse_service_send_goodbye(service, exitcode);
+	fuse_service_destroy(&service);
+
+	return fuse_service_exit(exitcode);
+}
+#else
+# define fuse_exfat_is_service(...)		(false)
+# define fuse_exfat_service_connect(...)	(0)
+# define fuse_exfat_service_mount(...)		(1)
+# define fuse_exfat_service_main(...)		(1)
+# define fuse_exfat_service_finish(ret)		(ret)
+#endif /* HAVE_EXFAT_FUSE_SERVICE */
+
 static struct exfat_node* get_node(const struct fuse_file_info* fi)
 {
 	return (struct exfat_node*) (size_t) fi->fh;
@@ -529,6 +629,12 @@ static char* add_user_option(char* options)
 
 	if (getuid() == 0)
 		return options;
+	if (fuse_exfat_is_service()) {
+		options = add_option(options, "uid", "0");
+		if (!options)
+			return NULL;
+		return add_option(options, "gid", "0");
+	}
 
 	pw = getpwuid(getuid());
 	if (pw == NULL || pw->pw_name == NULL)
@@ -601,12 +707,17 @@ static char* add_passthrough_fuse_options(char* fuse_options,
 static int fuse_exfat_main(char* mount_options, char* mount_point)
 {
 	char* argv[] = {"exfat", "-s", "-o", mount_options, mount_point, NULL};
+
+	if (fuse_exfat_is_service())
+		return fuse_exfat_service_main(argv, &fuse_exfat_ops);
+
 	return fuse_main(sizeof(argv) / sizeof(argv[0]) - 1, argv,
 			&fuse_exfat_ops, NULL);
 }
 
 int main(int argc, char* argv[])
 {
+	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
 	const char* spec = NULL;
 	char* mount_point = NULL;
 	char* fuse_options;
@@ -633,7 +744,11 @@ int main(int argc, char* argv[])
 		return 1;
 	}
 
-	while ((opt = getopt(argc, argv, "dno:Vv")) != -1)
+	rc = fuse_exfat_service_connect(&args);
+	if (rc)
+		exit(EXIT_FAILURE);
+
+	while ((opt = getopt(args.argc, args.argv, "dno:Vv")) != -1)
 	{
 		switch (opt)
 		{
@@ -675,16 +790,20 @@ int main(int argc, char* argv[])
 			break;
 		}
 	}
-	if (argc - optind != 2)
+	if (args.argc - optind != 2)
 	{
 		free(exfat_options);
 		free(fuse_options);
 		usage(argv[0]);
 	}
-	spec = argv[optind];
-	mount_point = argv[optind + 1];
+	spec = args.argv[optind];
+	mount_point = args.argv[optind + 1];
 
-	if (exfat_mount(&ef, spec, exfat_options) != 0)
+	if (fuse_exfat_is_service())
+		rc = fuse_exfat_service_mount(&ef, spec, exfat_options);
+	else
+		rc = exfat_mount(&ef, spec, exfat_options);
+	if (rc != 0)
 	{
 		free(exfat_options);
 		free(fuse_options);
@@ -704,5 +823,5 @@ int main(int argc, char* argv[])
 	rc = fuse_exfat_main(fuse_options, mount_point);
 
 	free(fuse_options);
-	return rc;
+	return fuse_exfat_service_finish(rc);
 }
diff --git a/libexfat/io.c b/libexfat/io.c
index 7af5316da70b4b..2a4c823979a9a8 100644
--- a/libexfat/io.c
+++ b/libexfat/io.c
@@ -86,7 +86,8 @@ static int open_rw(const char* spec)
 	return fd;
 }
 
-struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
+static struct exfat_dev* __exfat_open(int fd, const char* spec,
+				      enum exfat_mode mode)
 {
 	struct exfat_dev* dev;
 	struct stat stbuf;
@@ -119,6 +120,10 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
 		return NULL;
 	}
 
+	dev->fd = fd;
+	if (dev->fd >= 0)
+		goto opened;
+
 	switch (mode)
 	{
 	case EXFAT_MODE_RO:
@@ -162,6 +167,7 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
 		return NULL;
 	}
 
+opened:
 	if (fstat(dev->fd, &stbuf) != 0)
 	{
 		close(dev->fd);
@@ -284,6 +290,19 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
 	return dev;
 }
 
+struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
+{
+	return __exfat_open(-1, spec, mode);
+}
+
+struct exfat_dev* exfat_fdopen(int fd, const char* spec, enum exfat_mode mode)
+{
+	if (fd < 0)
+		return NULL;
+
+	return __exfat_open(fd, spec, mode);
+}
+
 int exfat_close(struct exfat_dev* dev)
 {
 	int rc = 0;
diff --git a/libexfat/mount.c b/libexfat/mount.c
index 86fb84db2445f5..dd6cf707d2ebbc 100644
--- a/libexfat/mount.c
+++ b/libexfat/mount.c
@@ -180,7 +180,8 @@ static void exfat_free(struct exfat* ef)
 	ef->sb = NULL;
 }
 
-int exfat_mount(struct exfat* ef, const char* spec, const char* options)
+static int __exfat_mount(struct exfat* ef, int fd, const char* spec,
+			 const char* options)
 {
 	int rc;
 	enum exfat_mode mode;
@@ -196,7 +197,10 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options)
 		mode = EXFAT_MODE_ANY;
 	else
 		mode = EXFAT_MODE_RW;
-	ef->dev = exfat_open(spec, mode);
+	if (fd >= 0)
+		ef->dev = exfat_fdopen(fd, spec, mode);
+	else
+		ef->dev = exfat_open(spec, mode);
 	if (ef->dev == NULL)
 		return -ENODEV;
 	if (exfat_get_mode(ef->dev) == EXFAT_MODE_RO)
@@ -340,6 +344,17 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options)
 	return -EIO;
 }
 
+int exfat_mount_from(struct exfat* ef, int fd, const char* spec,
+		     const char* options)
+{
+	return __exfat_mount(ef, fd, spec, options);
+}
+
+int exfat_mount(struct exfat* ef, const char* spec, const char* options)
+{
+	return __exfat_mount(ef, -1, spec, options);
+}
+
 static void finalize_super_block(struct exfat* ef)
 {
 	if (ef->ro)

  parent reply	other threads:[~2026-04-22 23:30 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-22 23:15 [PATCHBOMB v5] fuse/libfuse/e2fsprogs/etc: containerize ext4 for safer operation Darrick J. Wong
2026-04-22 23:18 ` [PATCHSET v5] libfuse: run fuse servers as a contained service Darrick J. Wong
2026-04-22 23:19   ` [PATCH 01/13] Refactor mount code / move common functions to mount_util.c Darrick J. Wong
2026-04-22 23:19   ` [PATCH 02/13] mount_service: add systemd socket service mounting helper Darrick J. Wong
2026-04-28 18:08     ` Darrick J. Wong
2026-04-29 15:23       ` Darrick J. Wong
2026-04-22 23:20   ` [PATCH 03/13] mount_service: create high level fuse helpers Darrick J. Wong
2026-04-22 23:20   ` [PATCH 04/13] mount_service: use the new mount api for the mount service Darrick J. Wong
2026-04-22 23:20   ` [PATCH 05/13] mount_service: update mtab after a successful mount Darrick J. Wong
2026-04-22 23:20   ` [PATCH 06/13] util: hoist the fuse.conf parsing and setuid mode enforcement code Darrick J. Wong
2026-04-26 20:42     ` Bernd Schubert
2026-04-27 14:40       ` Darrick J. Wong
2026-04-22 23:21   ` [PATCH 07/13] util: fix checkpatch complaints in fuser_conf.[ch] Darrick J. Wong
2026-04-22 23:21   ` [PATCH 08/13] mount_service: enable unprivileged users in a similar manner as fusermount Darrick J. Wong
2026-04-22 23:21   ` [PATCH 09/13] mount.fuse3: integrate systemd service startup Darrick J. Wong
2026-04-28 18:10     ` Darrick J. Wong
2026-04-22 23:21   ` [PATCH 10/13] mount_service: allow installation as a setuid program Darrick J. Wong
2026-04-22 23:22   ` [PATCH 11/13] example/service_ll: create a sample systemd service fuse server Darrick J. Wong
2026-04-26 21:28     ` Bernd Schubert
2026-04-27 14:51       ` Darrick J. Wong
2026-04-22 23:22   ` [PATCH 12/13] example/service: create a sample systemd service for a high-level " Darrick J. Wong
2026-04-26 21:04     ` Bernd Schubert
2026-04-27 15:04       ` Darrick J. Wong
2026-04-26 21:21     ` Bernd Schubert
2026-04-27 15:13       ` Darrick J. Wong
2026-04-22 23:22   ` [PATCH 13/13] nullfs: support fuse systemd service mode Darrick J. Wong
2026-04-26 16:35   ` [PATCHSET v5] libfuse: run fuse servers as a contained service Bernd Schubert
2026-04-26 16:56     ` Darrick J. Wong
2026-04-26 19:35       ` Bernd Schubert
2026-04-26 20:23         ` Bernd Schubert
2026-04-22 23:19 ` [PATCHSET 1/2] libext2fs: fix some missed fsync calls Darrick J. Wong
2026-04-22 23:23   ` [PATCH 1/3] libext2fs: always fsync the device when flushing the cache Darrick J. Wong
2026-04-22 23:23   ` [PATCH 2/3] libext2fs: always fsync the device when closing the unix IO manager Darrick J. Wong
2026-04-22 23:23   ` [PATCH 3/3] libext2fs: only fsync the unix fd if we wrote to the device Darrick J. Wong
2026-04-22 23:19 ` [PATCHSET v5 2/2] fuse4fs: run servers as a contained service Darrick J. Wong
2026-04-22 23:23   ` [PATCH 01/10] libext2fs: make it possible to extract the fd from an IO manager Darrick J. Wong
2026-04-22 23:24   ` [PATCH 02/10] libext2fs: fix checking for valid fds in mmp.c Darrick J. Wong
2026-04-22 23:24   ` [PATCH 03/10] unix_io: allow passing /dev/fd/XXX paths to the unixfd IO manager Darrick J. Wong
2026-04-22 23:24   ` [PATCH 04/10] libext2fs: fix MMP code to work with " Darrick J. Wong
2026-04-22 23:24   ` [PATCH 05/10] libext2fs: bump libfuse API version to 3.19 Darrick J. Wong
2026-04-22 23:25   ` [PATCH 06/10] fuse4fs: hoist some code out of fuse4fs_main Darrick J. Wong
2026-04-22 23:25   ` [PATCH 07/10] fuse4fs: enable safe service mode Darrick J. Wong
2026-04-22 23:25   ` [PATCH 08/10] fuse4fs: set proc title when in fuse " Darrick J. Wong
2026-04-22 23:25   ` [PATCH 09/10] fuse4fs: make MMP work correctly in safe " Darrick J. Wong
2026-04-22 23:26   ` [PATCH 10/10] debian: update packaging for fuse4fs service Darrick J. Wong
2026-04-22 23:29 ` [RFC PATCH 1/4] fusefatfs: enable fuse systemd service mode Darrick J. Wong
2026-04-22 23:30 ` Darrick J. Wong [this message]
2026-04-22 23:32 ` [RFC PATCH 3/4] fuseiso: enable " Darrick J. Wong
2026-04-22 23:32 ` [RFC PATCH 4/4] httpdirfs: enable fuse " Darrick J. Wong
2026-04-23  8:44 ` [PATCHBOMB v5] fuse/libfuse/e2fsprogs/etc: containerize ext4 for safer operation Amir Goldstein
2026-04-23 14:50   ` Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260422233045.GH7739@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=amir73il@gmail.com \
    --cc=bernd@bsbernd.com \
    --cc=brauner@kernel.org \
    --cc=demiobenour@gmail.com \
    --cc=fuse-devel@lists.linux.dev \
    --cc=joannelkoong@gmail.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=neal@gompa.dev \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.