public inbox for linux-fsdevel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Bernd Schubert <bernd@bsbernd.com>
Cc: linux-fsdevel@vger.kernel.org, Miklos Szeredi <miklos@szeredi.hu>,
	Joanne Koong <joannelkoong@gmail.com>, Kevin Chen <kchen@ddn.com>,
	Bernd Schubert <bschubert@ddn.com>
Subject: Re: [PATCH v2 22/25] Add support for sync-init of unprivileged daemons
Date: Mon, 30 Mar 2026 17:54:25 -0700	[thread overview]
Message-ID: <20260331005425.GI6202@frogsfrogsfrogs> (raw)
In-Reply-To: <20260326-fuse-init-before-mount-v2-22-b1ca8fcbf60f@bsbernd.com>

On Thu, Mar 26, 2026 at 10:34:55PM +0100, Bernd Schubert wrote:
> From: Bernd Schubert <bschubert@ddn.com>
> 
> This makes use of the bidirectional fusermount. Added is
> doc/README.mount, which explains the new bidirectional
> communication with fusermount.
> 
> Signed-off-by: Bernd Schubert <bschubert@ddn.com>
> ---
>  example/passthrough_hp.cc |   5 +-
>  include/fuse_daemonize.h  |  16 ++++--
>  include/fuse_lowlevel.h   |   8 +++
>  lib/fuse_daemonize.c      |  14 ++++--
>  lib/fuse_i.h              |   1 +
>  lib/fuse_lowlevel.c       | 121 ++++++++++++++++++++++++++++++++++++--------
>  lib/mount.c               | 126 +++++++++++++++++++++++++++++++++++++++++++++-
>  lib/mount_i_linux.h       |   7 +++
>  util/fusermount.c         |   2 -
>  9 files changed, 266 insertions(+), 34 deletions(-)
> 
> diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc
> index bad435077697e8832cf5a5195c17f2f873f2dfe6..cca865973ab5e8e9c1faa0fa28eb292a172a4812 100644
> --- a/example/passthrough_hp.cc
> +++ b/example/passthrough_hp.cc
> @@ -245,7 +245,7 @@ static void sfs_init(void *userdata, fuse_conn_info *conn)
>  	/* Try a large IO by default */
>  	conn->max_write = 4 * 1024 * 1024;
>  
> -	/* Signal successful init to parent */
> +	/* required here for async init */
>  	fuse_daemonize_success();
>  }
>  
> @@ -1661,6 +1661,9 @@ int main(int argc, char *argv[])
>  	if (teardown_watchog == NULL)
>  		goto err_out4;
>  
> +	/* required here for sync init */
> +	fuse_daemonize_success();
> +
>  	if (options.count("single"))
>  		ret = fuse_session_loop(se);
>  	else
> diff --git a/include/fuse_daemonize.h b/include/fuse_daemonize.h
> index 6215e42c635ba5956cb23ba0832dfc291ab8dede..6d3c4a6134f408d0f0a08b87495bde65d491286d 100644
> --- a/include/fuse_daemonize.h
> +++ b/include/fuse_daemonize.h
> @@ -42,6 +42,16 @@ int fuse_daemonize_start(unsigned int flags);
>  
>  /**
>   * Signal daemonization success to parent and cleanup.
> + *
> + * Note: For synchronous FUSE_INIT, this must be called after
> + *       fuse_session_mount() and before the first call to
> + *       fuse_session_loop*(). For asynchronous FUSE_INIT, this should
> + *       be called in the file system ->init() callback.
> + *
> + *       In order to simplify application code, this should be called from
> + *       the file system ->init() callback *and* after fuse_session_mount.
> + *       Libfuse knows internally if this is a sync or async FUSE_INIT
> + *       and will only signal the parent if the mount was completed.
>   */
>  void fuse_daemonize_success(void);

I wonder, could libfuse itself call fuse_daemonize_success from do_init
after the ->init function returns if !se->is_sync_init; or from the
end of fuse_session_mount otherwise?  In other words, hide this
particular detail from the fuse server?

Or are there things that a fuse server might want to do prior to calling
fuse_daemonize_success/fail?

> @@ -60,12 +70,12 @@ void fuse_daemonize_fail(int err);
>  bool fuse_daemonize_is_active(void);
>  
>  /**
> - * Set mounted flag.
> - *
> - * Called from fuse_session_mount().
> + * Set mounted flag. Called from fuse_session_mount().
>   */
>  void fuse_daemonize_set_mounted(void);
>  
> +void fuse_daemonize_set_got_init(void);
> +
>  /**
>   * Check if daemonization is used.
>   *
> diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
> index d85929e291a77de8caad7d6b3d9ac5b092ce0e62..ba7c4b3ac788f19f30fbf120fe8f6ae5851b425e 100644
> --- a/include/fuse_lowlevel.h
> +++ b/include/fuse_lowlevel.h
> @@ -2441,6 +2441,14 @@ int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf);
>   */
>  void fuse_session_want_sync_init(struct fuse_session *se);
>  
> +/**
> + * Check if the connection / session is using synchronous FUSE_INIT
> + *
> + * @param conn the connection
> + * @return true if using synchronous FUSE_INIT, false otherwise
> + */
> +bool fuse_conn_is_sync_init(struct fuse_conn_info *conn);
> +
>  /**
>   * Enable debug output
>   *
> diff --git a/lib/fuse_daemonize.c b/lib/fuse_daemonize.c
> index 97cfad7be879beacf69b020b7af78d512a224fd5..d4a34da15114fc0742394e72510946b63a98a252 100644
> --- a/lib/fuse_daemonize.c
> +++ b/lib/fuse_daemonize.c
> @@ -40,7 +40,8 @@ struct fuse_daemonize {
>  	bool watcher_started;
>  	_Atomic bool active;
>  	_Atomic bool daemonized;
> -	_Atomic bool mounted;
> +	_Atomic bool mounted;  /* fuse_session_mount() completed */
> +	_Atomic bool got_init; /* got FUSE_INIT */
>  };
>  
>  /* Global daemonization object pointer */
> @@ -238,9 +239,9 @@ static void fuse_daemonize_signal(int status)
>  	struct fuse_daemonize *dm = &daemonize;
>  	int rc;
>  
> -	/* Warn because there might be races */
> -	if (status == FUSE_DAEMONIZE_SUCCESS && !dm->mounted)
> -		fprintf(stderr, "fuse daemonize success without being mounted\n");
> +	/* The file system is not mounted yet - don't signal parent */
> +	if (status == FUSE_DAEMONIZE_SUCCESS && (!dm->mounted || !dm->got_init))
> +		return;
>  
>  	dm->active = false;
>  
> @@ -292,6 +293,11 @@ void fuse_daemonize_set_mounted(void)
>  	daemonize.mounted = true;
>  }
>  
> +void fuse_daemonize_set_got_init(void)
> +{
> +	daemonize.got_init = true;
> +}
> +
>  bool fuse_daemonize_is_used(void)
>  {
>  	return daemonize.active;
> diff --git a/lib/fuse_i.h b/lib/fuse_i.h
> index 164401e226eb727192a49e1cc7b38a75f031643b..20e9c275cbffade69d3fd440d1b48b371135bd84 100644
> --- a/lib/fuse_i.h
> +++ b/lib/fuse_i.h
> @@ -75,6 +75,7 @@ struct fuse_timeout_thread;
>  struct fuse_session {
>  	_Atomic(char *)mountpoint;
>  	int fd;
> +	_Atomic bool is_sync_init;
>  	struct fuse_custom_io *io;
>  	struct mount_opts *mo;
>  	int debug;
> diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
> index 4445e134a7ff5be508306f74db9d9c56e3582070..c4bb227b51a5226543adf7f037fb2c4604a5f978 100644
> --- a/lib/fuse_lowlevel.c
> +++ b/lib/fuse_lowlevel.c
> @@ -41,6 +41,7 @@
>  #include <assert.h>
>  #include <sys/file.h>
>  #include <sys/ioctl.h>
> +#include <sys/wait.h>
>  #include <stdalign.h>
>  #include <poll.h>
>  
> @@ -3024,6 +3025,7 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in,
>  	 * over the thread scheduling.
>  	 */
>  	se->got_init = 1;
> +	fuse_daemonize_set_got_init();
>  	send_reply_ok(req, &outarg, outargsize);
>  	if (enable_io_uring)
>  		fuse_uring_wake_ring_threads(se);
> @@ -4456,7 +4458,8 @@ static void *session_sync_init_worker(void *data)
>  }
>  
>  /* Enable synchronous FUSE_INIT and start worker thread */
> -static int session_start_sync_init(struct fuse_session *se, int fd)
> +static int session_start_sync_init(struct fuse_session *se, int fd,
> +				   bool *fall_back)
>  {
>  	int err, res;
>  
> @@ -4491,6 +4494,12 @@ static int session_start_sync_init(struct fuse_session *se, int fd)
>  		return err;
>  	}
>  
> +	/*
> +	 * If we get here, we know that sync init is enabled and fall back
> +	 * to the old mount API is not allowed
> +	 */
> +	*fall_back = false;
> +
>  	if (se->debug)
>  		fuse_log(FUSE_LOG_DEBUG,
>  				"fuse: synchronous FUSE_INIT enabled\n");
> @@ -4553,6 +4562,8 @@ static int session_wait_sync_init_completion(struct fuse_session *se)
>  		se->init_wakeup_fd = -1;
>  	}
>  
> +	se->init_thread = 0;
> +
>  	if (se->init_error != 0) {
>  		fuse_log(FUSE_LOG_ERR, "fuse: init worker failed: %s\n",
>  			 strerror(-se->init_error));
> @@ -4567,10 +4578,19 @@ static int session_wait_sync_init_completion(struct fuse_session *se)
>  	return 0;
>  }
>  
> +/*
> + * Mount using the new Linux mount API (fsopen/fsconfig/fsmount/move_mount)
> + * Sync-init is only supported with the new API, as the mount might hang
> + * in case of daemon crash during FUSE_INIT. That also means once the sync init
> + * ioctl succeed fallback is not allowed anymore.
> + * Returns: fd on success, -1 on failure
> + */
>  static int fuse_session_mount_new_api(struct fuse_session *se,
> -				      const char *mountpoint)
> +				      const char *mountpoint, bool *fall_back)
>  {
>  	int fd = -1;
> +	int sock_fd = -1;
> +	pid_t fusermount_pid = -1;
>  	int res, err;
>  	char *mnt_opts = NULL;
>  	char *mnt_opts_with_fd = NULL;
> @@ -4587,34 +4607,85 @@ static int fuse_session_mount_new_api(struct fuse_session *se,
>  	fd = fuse_kern_mount_prepare(mountpoint, se->mo);
>  	if (fd == -1) {
>  		fuse_log(FUSE_LOG_ERR, "Mount preparation failed.\n");
> -		err = -EIO;
>  		goto err;
>  	}
>  
> -	/*
> -	 * Enable synchronous FUSE_INIT and start worker thread, sync init
> -	 * failure is not an error
> -	 */
> +	*fall_back = true;
>  	se->fd = fd;
> -	err = session_start_sync_init(se, fd);
> +	err = session_start_sync_init(se, fd, fall_back);
>  	if (err)
>  		goto err;
>  
>  	snprintf(fd_opt, sizeof(fd_opt), "fd=%i", fd);
> +	err = -ENOMEM;
>  	if (fuse_opt_add_opt(&mnt_opts_with_fd, mnt_opts) == -1 ||
>  	    fuse_opt_add_opt(&mnt_opts_with_fd, fd_opt) == -1) {
> -		err = -ENOMEM;
>  		goto err;
>  	}
>  
> +	/* Try to mount directly */
>  	err = fuse_kern_fsmount_mo(mountpoint, se->mo, mnt_opts_with_fd);
> +
> +	/* If mount failed with EPERM, fall back to fusermount3 with sync-init */
> +	if (err < 0 && errno == EPERM) {
> +		if (se->debug)
> +			fuse_log(FUSE_LOG_DEBUG,
> +				 "fuse: privileged mount failed with EPERM, falling back to fusermount3\n");
> +
> +		/* Terminate worker thread with wrong fd */
> +		if (session_wait_sync_init_completion(se) < 0)
> +			fuse_log(FUSE_LOG_ERR, "fuse: sync init completion failed\n");
> +
> +		/* Close the privileged fd */
> +		close(fd);
> +		fd = -1;
> +		se->fd = -1;
> +		*fall_back = true; /* reset */
> +
> +		/* Call fusermount3 with --sync-init */
> +		err = -ENOTSUP;
> +		fd = mount_fusermount_obtain_fd(mountpoint, se->mo, mnt_opts,
> +						&sock_fd, &fusermount_pid);
> +		if (fd < 0) {
> +			fuse_log(
> +				FUSE_LOG_ERR,
> +				"fuse: fusermount3 sync-init failed\n");
> +			goto err;
> +		}
> +
> +		/* Start worker thread with correct fd from fusermount3 */
> +		se->fd = fd;
> +		err = session_start_sync_init(se, fd, fall_back);
> +		if (err)
> +			fuse_log(FUSE_LOG_ERR,
> +				"fuse: failed to start sync init worker\n");
> +
> +		/* Send proceed signal and wait for mount result */
> +		err = fuse_fusermount_proceed_mnt(sock_fd);
> +		if (err < 0) {
> +			err = -EIO;
> +			goto err_with_sock;
> +		}
> +	} else if (err < 0) {
> +		/* Mount failed with non-EPERM error, bail out */
> +		goto err;
> +	}

I wonder if you could reduce the indent levels with

	if (err == 0 || (err < 0 && errno == EPERM))
		goto err;

	/* all the fallback code */

It's really a pity that C makes us do all this boilerplate.  Though it's
also a little funny to have a library that prints error messages.

Eh, that's a stylistic preference.  The logic looks correct. :)

> +
> +err_with_sock:
> +	if (sock_fd >= 0) {
> +		close(sock_fd);
> +		/* Reap fusermount3 child process to prevent zombie */
> +		if (fusermount_pid > 0)
> +			waitpid(fusermount_pid, NULL, 0);
> +	}
>  err:
>  	if (err < 0) {
> +		/* Close fd first to unblock worker thread */
>  		if (fd >= 0)
>  			close(fd);
>  		fd = -1;
>  		se->fd = -1;
> -		se->error = -errno;
> +		se->error = err;
>  	}
>  	/* Wait for synchronous FUSE_INIT to complete */
>  	if (session_wait_sync_init_completion(se) < 0)
> @@ -4626,10 +4697,11 @@ err:
>  }
>  #else
>  static int fuse_session_mount_new_api(struct fuse_session *se,
> -				      const char *mountpoint)
> +				      const char *mountpoint, bool *fall_back)
>  {
>  	(void) se;
>  	(void) mountpoint;
> +	(void) fall_back;
>  
>  	return -1;
>  }
> @@ -4639,6 +4711,7 @@ int fuse_session_mount(struct fuse_session *se, const char *_mountpoint)
>  {
>  	int fd;
>  	char *mountpoint;
> +	bool fall_back;
>  
>  	if (_mountpoint == NULL) {
>  		fuse_log(FUSE_LOG_ERR, "Invalid null-ptr mountpoint!\n");
> @@ -4682,21 +4755,18 @@ int fuse_session_mount(struct fuse_session *se, const char *_mountpoint)
>  		return 0;
>  	}
>  
> -	/* new linux mount api */
> -	fd = fuse_session_mount_new_api(se, mountpoint);
> -	if (fd >= 0)
> -		goto out;
> +	/* new linux mount api (and sync init) */
> +	fd = fuse_session_mount_new_api(se, mountpoint, &fall_back);
>  
>  	/* fall back to old API */
> -	se->error = 0; /* reset error of new api */
> -	fd = fuse_kern_mount(mountpoint, se->mo);
> -	if (fd < 0)
> -		goto error_out;
> +	if (fall_back && fd < 0) {
> +		se->error = 0; /* reset error of new api */
> +		fd = fuse_kern_mount(mountpoint, se->mo);
> +		if (fd < 0)
> +			goto error_out;
> +	}
>  
> -out:
>  	se->fd = fd;
> -
> -	/* Save mountpoint */
>  	se->mountpoint = mountpoint;
>  
>  	fuse_daemonize_set_mounted();
> @@ -5015,3 +5085,10 @@ void fuse_session_set_debug(struct fuse_session *se)
>  {
>  	se->debug = 1;
>  }
> +
> +bool fuse_conn_is_sync_init(struct fuse_conn_info *conn)
> +{
> +	struct fuse_session *se = container_of(conn, struct fuse_session, conn);
> +
> +	return se->is_sync_init;
> +}
> diff --git a/lib/mount.c b/lib/mount.c
> index 408e9d36896048fc167e264c95b6f6e31d86679f..f0d12525310a9ad239c0f447af60bd49b105a091 100644
> --- a/lib/mount.c
> +++ b/lib/mount.c
> @@ -37,6 +37,7 @@
>  #define FUSERMOUNT_PROG		"fusermount3"
>  #define FUSE_COMMFD_ENV		"_FUSE_COMMFD"
>  #define FUSE_COMMFD2_ENV	"_FUSE_COMMFD2"
> +#define ARG_FD_ENTRY_SIZE	30
>  
>  	enum { KEY_KERN_FLAG,
>  	       KEY_KERN_OPT,
> @@ -306,7 +307,7 @@ static int setup_auto_unmount(const char *mountpoint, int quiet)
>  		return -1;
>  	}
>  
> -	char arg_fd_entry[30];
> +	char arg_fd_entry[ARG_FD_ENTRY_SIZE];
>  	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
>  	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
>  	/*
> @@ -379,7 +380,7 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
>  		return -1;
>  	}
>  
> -	char arg_fd_entry[30];
> +	char arg_fd_entry[ARG_FD_ENTRY_SIZE];
>  	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
>  	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
>  	/*
> @@ -439,6 +440,127 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
>  	return fd;
>  }
>  
> +/*
> + * Mount using fusermount3 with --sync-init flag for bidirectional fd exchange
> + * Used by new mount API when privileged mount fails with EPERM
> + *
> + * Returns: fd on success, -1 on failure

What fd is in the return value?  The /dev/fuse that fusermount opened,
right?

> + * On success, *sock_fd_out contains the socket fd for signaling fusermount3
> + */
> +int mount_fusermount_obtain_fd(const char *mountpoint, struct mount_opts *mo,
> +			       const char *opts, int *sock_fd_out,
> +			       pid_t *pid_out)
> +{
> +	int fds[2];
> +	pid_t pid;
> +	int res;
> +	char arg_fd_entry[ARG_FD_ENTRY_SIZE];
> +	posix_spawn_file_actions_t action;
> +	int fd, status;
> +
> +	(void)mo;
> +
> +	if (!mountpoint) {
> +		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
> +		return -1;
> +	}
> +
> +	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
> +	if (res == -1) {
> +		fuse_log(FUSE_LOG_ERR, "Running %s: socketpair() failed: %s\n",
> +			 FUSERMOUNT_PROG, strerror(errno));
> +		return -1;
> +	}
> +
> +	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
> +	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
> +	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[1]);
> +	setenv(FUSE_COMMFD2_ENV, arg_fd_entry, 1);
> +
> +	char const *const argv[] = {
> +		FUSERMOUNT_PROG,
> +		"--sync-init",
> +		"-o", opts ? opts : "",
> +		"--",
> +		mountpoint,
> +		NULL,
> +	};
> +
> +	posix_spawn_file_actions_init(&action);
> +	posix_spawn_file_actions_addclose(&action, fds[1]);
> +	status = fusermount_posix_spawn(&action, argv, &pid);
> +	posix_spawn_file_actions_destroy(&action);

Huh.  Would have been nice to have known about posix_spawn when I was
writing xfs_healer.

> +
> +	if (status != 0) {
> +		close(fds[0]);
> +		close(fds[1]);
> +		return -1;
> +	}
> +
> +	close(fds[0]);
> +
> +	fd = receive_fd(fds[1]);
> +	if (fd < 0) {
> +		close(fds[1]);
> +		waitpid(pid, NULL, 0);
> +		return -1;
> +	}
> +
> +	fcntl(fd, F_SETFD, FD_CLOEXEC);
> +
> +	/* Return socket fd for later signaling */
> +	*sock_fd_out = fds[1];
> +	*pid_out = pid;
> +
> +	return fd;
> +}
> +
> +/*
> + * Send proceed signal to fusermount3 and wait for mount result
> + * Returns: 0 on success, -1 on failure
> + */
> +int fuse_fusermount_proceed_mnt(int sock_fd)
> +{
> +	char buf = '\0';
> +	ssize_t res;
> +
> +	/* Send proceed signal */
> +	do {
> +		res = send(sock_fd, &buf, 1, 0);
> +	} while (res == -1 && errno == EINTR);

Hrmm, I probably need to wrap the sendmsg/recvmsg calls in my own
patches to do this loop, don't I?

--D

> +
> +	if (res != 1) {
> +		fuse_log(FUSE_LOG_ERR, "fuse: failed to send proceed signal: %s\n",
> +			 strerror(errno));
> +		return -1;
> +	}
> +
> +	/* Wait for mount result from fusermount3 (4-byte error code) */
> +	int32_t status;
> +
> +	do {
> +		res = recv(sock_fd, &status, sizeof(status), 0);
> +	} while (res == -1 && errno == EINTR);
> +
> +	if (res != sizeof(status)) {
> +		if (res == 0)
> +			fuse_log(FUSE_LOG_ERR, "fuse: fusermount3 closed connection\n");
> +		else
> +			fuse_log(FUSE_LOG_ERR, "fuse: failed to receive mount status: %s\n",
> +				 strerror(errno));
> +		return -1;
> +	}
> +
> +	if (status != 0) {
> +		if (status != -EPERM)
> +			fuse_log(FUSE_LOG_ERR, "fuse: fusermount3 mount failed: %s\n",
> +				 strerror(-status));
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  #ifndef O_CLOEXEC
>  #define O_CLOEXEC 0
>  #endif
> diff --git a/lib/mount_i_linux.h b/lib/mount_i_linux.h
> index 597b380076fccc1d38fd4d0b9108fc92a1adfa62..ae98296a334a2aa39c4f3e5c3e4e3c136ae38cd3 100644
> --- a/lib/mount_i_linux.h
> +++ b/lib/mount_i_linux.h
> @@ -43,4 +43,11 @@ int fuse_kern_fsmount_mo(const char *mnt, struct mount_opts *mo,
>  
>  char *fuse_mnt_build_source(const struct mount_opts *mo);
>  char *fuse_mnt_build_type(const struct mount_opts *mo);
> +int mount_fusermount_obtain_fd(const char *mountpoint,
> +					   struct mount_opts *mo,
> +					   const char *opts, int *sock_fd_out,
> +					   pid_t *pid_out);
> +
> +int fuse_fusermount_proceed_mnt(int sock_fd);
> +
>  #endif /* FUSE_MOUNT_I_LINUX_H_ */
> diff --git a/util/fusermount.c b/util/fusermount.c
> index 31bf959024ae0cd2a4e50974589bfab30a100b0a..bf442416c83d6da3f80eca5c9814df29f61bec56 100644
> --- a/util/fusermount.c
> +++ b/util/fusermount.c
> @@ -1323,7 +1323,6 @@ struct mount_context {
>  	char *source;
>  	char *mnt_opts;
>  	char *x_opts;
> -	const char *type;
>  };
>  
>  /*
> @@ -1447,7 +1446,6 @@ static int mount_fuse_finish_fsmount(const char *mnt, const char *opts,
>  
>  	/* Store results in context */
>  	ctx->source = mp.source;
> -	ctx->type = mp.type;
>  	ctx->mnt_opts = final_mnt_opts;
>  	*type = mp.type;
>  
> 
> -- 
> 2.43.0
> 
> 

  reply	other threads:[~2026-03-31  0:54 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-26 21:34 [PATCH v2 00/25] libfuse: Add support for synchronous init Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 01/25] ci-build: Add environment logging Bernd Schubert
2026-03-27  3:20   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 02/25] Add 'STRCPY' to the checkpatch ignore option Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 03/25] checkpatch.pl: Add _Atomic to $Attribute patttern Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 04/25] Add a new daemonize API Bernd Schubert
2026-03-27 22:06   ` Darrick J. Wong
2026-03-27 23:07     ` Bernd Schubert
2026-03-28  4:01       ` Darrick J. Wong
2026-03-30 17:45       ` Darrick J. Wong
2026-03-30 18:26         ` Bernd Schubert
2026-03-30 21:25           ` Darrick J. Wong
2026-03-30 17:55   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 05/25] Sync fuse_kernel.h with linux-6.18 Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 06/25] mount.c: Split fuse_mount_sys to prepare privileged sync FUSE_INIT Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 07/25] Add FUSE_MOUNT_FALLBACK_NEEDED define for -2 mount errors Bernd Schubert
2026-03-27  3:20   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 08/25] Refactor mount code / move common functions to mount_util.c Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 09/25] Use asprintf() for fuse_mnt_build_{source,type} Bernd Schubert
2026-03-27  3:24   ` Darrick J. Wong
2026-03-30 15:34     ` Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 10/25] lib/mount.c: Remove some BSD ifdefs Bernd Schubert
2026-03-27  3:28   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 11/25] Move 'struct mount_flags' to util.h Bernd Schubert
2026-03-30 18:11   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 12/25] conftest.py: Add more valgrind filter patterns Bernd Schubert
2026-03-30 18:16   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 13/25] Add support for the new linux mount API Bernd Schubert
2026-03-30 18:27   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 14/25] fuse mount: Support synchronous FUSE_INIT (privileged daemon) Bernd Schubert
2026-03-30 18:44   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 15/25] Add fuse_session_set_debug() to enable debug output without foreground Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 16/25] Move more generic mount code to mount_util.{c,h} Bernd Schubert
2026-03-30 18:47   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 17/25] Split the fusermount do_mount function Bernd Schubert
2026-03-30 18:48   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 18/25] fusermout: Remove the large read check Bernd Schubert
2026-03-27  3:32   ` Darrick J. Wong
2026-03-30 15:26     ` Bernd Schubert
2026-03-30 17:57       ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 19/25] fusermount: Refactor extract_x_options Bernd Schubert
2026-03-26 21:34 ` [PATCH v2 20/25] Make fusermount work bidirectional for sync init Bernd Schubert
2026-03-30 19:03   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 21/25] New mount API: Filter out "user=" Bernd Schubert
2026-03-27  3:32   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 22/25] Add support for sync-init of unprivileged daemons Bernd Schubert
2026-03-31  0:54   ` Darrick J. Wong [this message]
2026-03-26 21:34 ` [PATCH v2 23/25] Move fuse_mnt_build_{source,type} to mount_util.c Bernd Schubert
2026-03-30 19:04   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 24/25] Add mount and daemonization README documents Bernd Schubert
2026-03-31  1:17   ` Darrick J. Wong
2026-03-26 21:34 ` [PATCH v2 25/25] Add a background debug option to passthrough hp Bernd Schubert
2026-03-30 19:04   ` 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=20260331005425.GI6202@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=bernd@bsbernd.com \
    --cc=bschubert@ddn.com \
    --cc=joannelkoong@gmail.com \
    --cc=kchen@ddn.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox