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>
Subject: Re: [PATCH v2 04/25] Add a new daemonize API
Date: Mon, 30 Mar 2026 10:55:48 -0700	[thread overview]
Message-ID: <20260330175548.GS6202@frogsfrogsfrogs> (raw)
In-Reply-To: <20260326-fuse-init-before-mount-v2-4-b1ca8fcbf60f@bsbernd.com>

On Thu, Mar 26, 2026 at 10:34:37PM +0100, Bernd Schubert wrote:
> Existing example/ file systems do the fuse_daemonize() after
> fuse_session_mount() - i.e. after the mount point is already
> established. Though, these example/ daemons do not start
> extra threads and do not need network initialization either.
> 
> fuse_daemonize() also does not allow to return notification
> from the forked child to the parent.
> 
> Complex fuse file system daemons often want the order of
> 1) fork - parent watches, child does the work
> 
> Child:
>     2) start extra threads and system initialization (like network
>        connection and RDMA memory registration) from the fork child.
>     3) Start the fuse session after everything else succeeded
> 
> Parent:
>     Report child initialization success or failure
> 
> A new API is introduced to overcome the limitations of
> fuse_daemonize()
> 
> fuse_daemonize_start() - fork, but foreground process does not
> terminate yet and watches the background.
> 
> fuse_daemonize_success() / fuse_daemonize_fail() - background
> daemon signals to the foreground process success or failure.
> 
> fuse_daemonize_active() - helper function for the high level
> interface, which needs to handle both APIs. fuse_daemonize()
> is called within fuse_main(), which now needs to know if the caller
> actually already used the new API itself.
> 
> The object 'struct fuse_daemonize *' is allocated dynamically
> and stored a global variable in fuse_daemonize.c, because
> - high level fuse_main_real_versioned() needs to know
> if already daemonized
> - high level daemons do not have access to struct fuse_session
> - FUSE_SYNC_INIT in later commits can only be done if the new
> API (or a file system internal) daemonization is used.
> 
> Signed-off-by: Bernd Schubert <bernd@bsbernd.com>

Only a couple nitpicks now...

> ---
>  example/passthrough_hp.cc   |  18 ++-
>  include/fuse_daemonize.h    |  74 +++++++++++
>  include/meson.build         |   3 +-
>  lib/fuse_daemonize.c        | 292 ++++++++++++++++++++++++++++++++++++++++++++
>  lib/fuse_i.h                |   4 +-
>  lib/fuse_lowlevel.c         |   3 +
>  lib/fuse_versionscript      |   4 +
>  lib/helper.c                |  13 +-
>  lib/meson.build             |   3 +-
>  test/test_want_conversion.c |   1 +
>  10 files changed, 404 insertions(+), 11 deletions(-)
> 
> diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc
> index 9f795c5546ee8312e1393c5b8fcebfd77724fb49..bad435077697e8832cf5a5195c17f2f873f2dfe6 100644
> --- a/example/passthrough_hp.cc
> +++ b/example/passthrough_hp.cc
> @@ -55,6 +55,7 @@
>  #include <errno.h>
>  #include <ftw.h>
>  #include <fuse_lowlevel.h>
> +#include <fuse_daemonize.h>
>  #include <inttypes.h>
>  #include <string.h>
>  #include <sys/file.h>
> @@ -243,6 +244,9 @@ 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 */
> +	fuse_daemonize_success();
>  }
>  
>  static void sfs_getattr(fuse_req_t req, fuse_ino_t ino, fuse_file_info *fi)
> @@ -1580,6 +1584,7 @@ int main(int argc, char *argv[])
>  {
>  	struct fuse_loop_config *loop_config = NULL;
>  	void *teardown_watchog = NULL;
> +	unsigned int daemon_flags = 0;
>  
>  	// Parse command line options
>  	auto options{ parse_options(argc, argv) };
> @@ -1638,10 +1643,14 @@ int main(int argc, char *argv[])
>  
>  	fuse_loop_cfg_set_clone_fd(loop_config, fs.clone_fd);
>  
> -	if (fuse_session_mount(se, argv[2]) != 0)
> +	/* Start daemonization before mount so parent can report mount failure */
> +	if (fs.foreground)
> +		daemon_flags |= FUSE_DAEMONIZE_NO_BACKGROUND;
> +	if (fuse_daemonize_start(daemon_flags) != 0)
>  		goto err_out3;
>  
> -	fuse_daemonize(fs.foreground);

Should the old fuse_daemonize() no-op (or complain) if the client has
already called fuse_daemonize_start()?  You've done something like that
in fuse_main_real_versioned, so maybe it should be automatic.

> +	if (fuse_session_mount(se, argv[2]) != 0)
> +		goto err_out4;
>  
>  	if (!fs.foreground)
>  		fuse_log_enable_syslog("passthrough-hp", LOG_PID | LOG_CONS,
> @@ -1650,7 +1659,7 @@ int main(int argc, char *argv[])
>  	teardown_watchog = fuse_session_start_teardown_watchdog(
>  		se, fs.root.stop_timeout_secs, NULL, NULL);
>  	if (teardown_watchog == NULL)
> -		goto err_out3;
> +		goto err_out4;
>  
>  	if (options.count("single"))
>  		ret = fuse_session_loop(se);
> @@ -1659,6 +1668,9 @@ int main(int argc, char *argv[])
>  
>  	fuse_session_unmount(se);
>  
> +err_out4:
> +	if (fuse_daemonize_is_active())
> +		fuse_daemonize_fail(ret);
>  err_out3:
>  	fuse_remove_signal_handlers(se);
>  err_out2:
> diff --git a/include/fuse_daemonize.h b/include/fuse_daemonize.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..c35dddd668b399535c53b44ab06c65fc0b3ddefa
> --- /dev/null
> +++ b/include/fuse_daemonize.h
> @@ -0,0 +1,74 @@
> +/*
> + * FUSE: Filesystem in Userspace
> + * Copyright (C) 2026 Bernd Schubert <bsbernd.com>
> + *
> + * This program can be distributed under the terms of the GNU LGPLv2.
> + * See the file COPYING.LIB.
> + *
> + */
> +
> +#ifndef FUSE_DAEMONIZE_H_
> +#define FUSE_DAEMONIZE_H_
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Flags for fuse_daemonize_start()
> + */
> +#define FUSE_DAEMONIZE_NO_CHDIR      (1 << 0)
> +#define FUSE_DAEMONIZE_NO_BACKGROUND (1 << 1)
> +
> +/**
> + * Start daemonization process.
> + *
> + * Unless FUSE_DAEMONIZE_NO_BACKGROUND is set, this forks the process.
> + * The parent waits for a signal from the child via fuse_daemonize_success()
> + * or fuse_daemonize_fail().
> + * The child returns from this call and continues setup.
> + *
> + * Unless FUSE_DAEMONIZE_NO_CHDIR is set, changes directory to "/".
> + *
> + * Must be called before fuse_session_mount().
> + *
> + * @param flags combination of FUSE_DAEMONIZE_* flags
> + * @return 0 on success, negative errno on error
> + */
> +int fuse_daemonize_start(unsigned int flags);
> +
> +/**
> + * Signal daemonization success to parent and cleanup.
> + */
> +void fuse_daemonize_success(void);
> +
> +/**
> + * Signal daemonization failure to parent and cleanup.
> + *
> + * @param err error code to pass to parent

I think this should say explicitly that @err will become the exit code
of the parent process.

It might also be useful to state that except for fuse_daemonize_start,
all the other APIs must only be called from the child process.

--D

> + */
> +void fuse_daemonize_fail(int err);
> +
> +/**
> + * Check if daemonization is active and waiting for signal.
> + *
> + * @return true if active, false otherwise
> + */
> +bool fuse_daemonize_is_active(void);
> +
> +/**
> + * Set mounted flag.
> + *
> + * Called from fuse_session_mount().
> + */
> +void fuse_daemonize_set_mounted(void);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* FUSE_DAEMONIZE_H_ */
> +
> diff --git a/include/meson.build b/include/meson.build
> index bf671977a5a6a9142bd67aceabd8a919e3d968d0..cfbaf52ac5d84369e92948c631e2fcfdd04ac2eb 100644
> --- a/include/meson.build
> +++ b/include/meson.build
> @@ -1,4 +1,5 @@
>  libfuse_headers = [ 'fuse.h', 'fuse_common.h', 'fuse_lowlevel.h',
> -	            'fuse_opt.h', 'cuse_lowlevel.h', 'fuse_log.h' ]
> +	            'fuse_opt.h', 'cuse_lowlevel.h', 'fuse_log.h',
> +	            'fuse_daemonize.h' ]
>  
>  install_headers(libfuse_headers, subdir: 'fuse3')
> diff --git a/lib/fuse_daemonize.c b/lib/fuse_daemonize.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..865acad7db56dbe5ed8a1bee52e7353627e89b75
> --- /dev/null
> +++ b/lib/fuse_daemonize.c
> @@ -0,0 +1,292 @@
> +/*
> + * FUSE: Filesystem in Userspace
> + * Copyright (C) 2026 Bernd Schubert <bsbernd.com>
> + *
> + * This program can be distributed under the terms of the GNU LGPLv2.
> + * See the file COPYING.LIB.
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include "fuse_daemonize.h"
> +
> +#include <fcntl.h>
> +#include <poll.h>
> +#include <pthread.h>
> +#include <stdatomic.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +
> +/**
> + * Status values for fuse_daemonize_success() and fuse_daemonize_fail()
> + */
> +#define FUSE_DAEMONIZE_SUCCESS 0
> +#define FUSE_DAEMONIZE_FAILURE 1
> +
> +/* Private/internal data  */
> +struct fuse_daemonize {
> +	unsigned int flags;
> +	int signal_pipe_wr;	/* write end for signaling parent */
> +	int death_pipe_rd;	/* read end, POLLHUP when parent dies */
> +	int stop_pipe_rd;	/* read end for stop signal */
> +	int stop_pipe_wr;	/* write end for stop signal */
> +	pthread_t watcher;
> +	bool watcher_started;
> +	_Atomic bool active;
> +	_Atomic bool daemonized;
> +	_Atomic bool mounted;
> +};
> +
> +/* Global daemonization object pointer */
> +static struct fuse_daemonize daemonize = {
> +	.signal_pipe_wr = -1,
> +	.death_pipe_rd = -1,
> +	.stop_pipe_rd = -1,
> +	.stop_pipe_wr = -1,
> +};
> +
> +/* Watcher thread: polls for parent death or stop signal */
> +static void *parent_watcher_thread(void *arg)
> +{
> +	struct fuse_daemonize *di = arg;
> +	struct pollfd pfd[2];
> +
> +	pfd[0].fd = di->death_pipe_rd;
> +	pfd[0].events = POLLIN;
> +	pfd[1].fd = di->stop_pipe_rd;
> +	pfd[1].events = POLLIN;
> +
> +	while (1) {
> +		int rc = poll(pfd, 2, -1);
> +
> +		if (rc < 0)
> +			continue;
> +
> +		/* Parent died - death pipe write end closed */
> +		if (pfd[0].revents & (POLLHUP | POLLERR))
> +			_exit(EXIT_FAILURE);
> +
> +		/* Stop signal received */
> +		if (pfd[1].revents & POLLIN)
> +			break;
> +	}
> +	return NULL;
> +}
> +
> +static int start_parent_watcher(struct fuse_daemonize *daemonize)
> +{
> +	int rc;
> +
> +	rc = pthread_create(&daemonize->watcher, NULL, parent_watcher_thread,
> +			    daemonize);
> +	if (rc != 0) {
> +		fprintf(stderr, "fuse_daemonize: pthread_create: %s\n",
> +			strerror(rc));
> +		return -rc;
> +	}
> +	daemonize->watcher_started = true;
> +	return 0;
> +}
> +
> +static void stop_parent_watcher(struct fuse_daemonize *daemonize)
> +{
> +	char byte = 0;
> +
> +	if (daemonize && daemonize->watcher_started) {
> +		/* Signal watcher to stop */
> +		if (write(daemonize->stop_pipe_wr, &byte, 1) != 1)
> +			perror("fuse_daemonize: stop write");
> +		pthread_join(daemonize->watcher, NULL);
> +		daemonize->watcher_started = false;
> +	}
> +}
> +
> +static int daemonize_child(struct fuse_daemonize *daemonize)
> +{
> +	int stop_pipe[2], err = 0;
> +
> +	if (pipe(stop_pipe) == -1) {
> +		err = -errno;
> +		perror("fuse_daemonize_start: stop pipe");
> +		return err;
> +	}
> +	daemonize->stop_pipe_rd = stop_pipe[0];
> +	daemonize->stop_pipe_wr = stop_pipe[1];
> +
> +	if (setsid() == -1) {
> +		err = -errno;
> +		perror("fuse_daemonize_start: setsid");
> +		goto err_close_stop;
> +	}
> +
> +	/* Close stdin immediately */
> +	int nullfd = open("/dev/null", O_RDWR, 0);
> +
> +	if (nullfd != -1) {
> +		(void)dup2(nullfd, 0);
> +		if (nullfd > 0)
> +			close(nullfd);
> +	}
> +
> +	/* Start watcher thread to detect parent death */
> +	err = start_parent_watcher(daemonize);
> +	if (err)
> +		goto err_close_stop;
> +
> +	daemonize->daemonized = true;
> +	return 0;
> +
> +err_close_stop:
> +	close(daemonize->stop_pipe_rd);
> +	close(daemonize->stop_pipe_wr);
> +	return err;
> +}
> +
> +/* Fork and daemonize. Returns 0 in child, never returns in parent. */
> +static int do_daemonize(struct fuse_daemonize *daemonize)
> +{
> +	int signal_pipe[2], death_pipe[2], err;
> +
> +	if (pipe(signal_pipe) == -1) {
> +		err = -errno;
> +		perror("fuse_daemonize_start: signal pipe");
> +		return err;
> +	}
> +
> +	if (pipe(death_pipe) == -1) {
> +		err = -errno;
> +		perror("fuse_daemonize_start: death pipe");
> +		close(signal_pipe[0]);
> +		close(signal_pipe[1]);
> +		return err;
> +	}
> +
> +	switch (fork()) {
> +	case -1:
> +		err = -errno;
> +		perror("fuse_daemonize_start: fork");
> +		close(signal_pipe[0]);
> +		close(signal_pipe[1]);
> +		close(death_pipe[0]);
> +		close(death_pipe[1]);
> +		return err;
> +
> +	case 0:
> +		/* Child: signal write end, death read end */
> +		close(signal_pipe[0]);
> +		close(death_pipe[1]);
> +		daemonize->signal_pipe_wr = signal_pipe[1];
> +		daemonize->death_pipe_rd = death_pipe[0];
> +		return daemonize_child(daemonize);
> +
> +	default: {
> +		/* Parent: signal read end, death write end (kept open) */
> +		int status;
> +		ssize_t res;
> +
> +		close(signal_pipe[1]);
> +		close(death_pipe[0]);
> +
> +		res = read(signal_pipe[0], &status, sizeof(status));
> +		close(signal_pipe[0]);
> +		close(death_pipe[1]);
> +
> +		if (res != sizeof(status))
> +			_exit(EXIT_FAILURE);
> +		_exit(status);
> +	}
> +	}
> +}
> +
> +int fuse_daemonize_start(unsigned int flags)
> +{
> +	struct fuse_daemonize *dm = &daemonize;
> +	int err = 0;
> +
> +	dm->flags = flags;
> +	dm->signal_pipe_wr = -1;
> +	dm->death_pipe_rd = -1;
> +	dm->stop_pipe_rd = -1;
> +	dm->stop_pipe_wr = -1;
> +	dm->active = true;
> +
> +	if (!(flags & FUSE_DAEMONIZE_NO_CHDIR))
> +		(void)chdir("/");
> +
> +	if (!(flags & FUSE_DAEMONIZE_NO_BACKGROUND))
> +		err = do_daemonize(dm);
> +
> +	return err;
> +}
> +
> +static void close_if_valid(int *fd)
> +{
> +	if (*fd != -1) {
> +		close(*fd);
> +		*fd = -1;
> +	}
> +}
> +
> +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");
> +
> +	dm->active = false;
> +
> +	/* Stop watcher before signaling - parent will exit after this */
> +	stop_parent_watcher(dm);
> +
> +	/* Signal status to parent */
> +	if (dm->signal_pipe_wr != -1) {
> +		rc = write(dm->signal_pipe_wr, &status, sizeof(status));
> +		if (rc != sizeof(status))
> +			fprintf(stderr, "%s: write failed\n", __func__);
> +	}
> +
> +	/* Redirect stdout/stderr to /dev/null on success */
> +	if (status == FUSE_DAEMONIZE_SUCCESS && dm->daemonized) {
> +		int nullfd = open("/dev/null", O_RDWR, 0);
> +
> +		if (nullfd != -1) {
> +			(void)dup2(nullfd, 1);
> +			(void)dup2(nullfd, 2);
> +			if (nullfd > 2)
> +				close(nullfd);
> +		}
> +	}
> +
> +	close_if_valid(&dm->signal_pipe_wr);
> +	close_if_valid(&dm->death_pipe_rd);
> +	close_if_valid(&dm->stop_pipe_rd);
> +	close_if_valid(&dm->stop_pipe_wr);
> +}
> +
> +void fuse_daemonize_success(void)
> +{
> +	fuse_daemonize_signal(FUSE_DAEMONIZE_SUCCESS);
> +}
> +
> +void fuse_daemonize_fail(int err)
> +{
> +	fuse_daemonize_signal(err);
> +}
> +
> +bool fuse_daemonize_is_active(void)
> +{
> +	return daemonize.daemonized || daemonize.active;
> +}
> +
> +void fuse_daemonize_set_mounted(void)
> +{
> +	daemonize.mounted = true;
> +}
> diff --git a/lib/fuse_i.h b/lib/fuse_i.h
> index 65d2f68f7f30918a3c3ee4d473796cb013428a8f..9e3c5dc5021e210a2778e975a37ab609af324010 100644
> --- a/lib/fuse_i.h
> +++ b/lib/fuse_i.h
> @@ -17,7 +17,6 @@
>  #include <semaphore.h>
>  #include <stdint.h>
>  #include <stdbool.h>
> -#include <errno.h>
>  #include <stdatomic.h>
>  
>  #define MIN(a, b) \
> @@ -110,6 +109,9 @@ struct fuse_session {
>  	/* true if reading requests from /dev/fuse are handled internally */
>  	bool buf_reallocable;
>  
> +	/* synchronous FUSE_INIT support */
> +	bool want_sync_init;
> +
>  	/* io_uring */
>  	struct fuse_session_uring uring;
>  
> diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
> index 3234f0ce3b246a4c2c40dc0757177de91b6608b2..ccff6a768f0b8c32469abda9405ff29623f3fff7 100644
> --- a/lib/fuse_lowlevel.c
> +++ b/lib/fuse_lowlevel.c
> @@ -19,6 +19,7 @@
>  #include "mount_util.h"
>  #include "util.h"
>  #include "fuse_uring_i.h"
> +#include "fuse_daemonize.h"
>  
>  #include <pthread.h>
>  #include <stdatomic.h>
> @@ -4451,6 +4452,8 @@ int fuse_session_mount(struct fuse_session *se, const char *_mountpoint)
>  	/* Save mountpoint */
>  	se->mountpoint = mountpoint;
>  
> +	fuse_daemonize_set_mounted();
> +
>  	return 0;
>  
>  error_out:
> diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
> index cce09610316f4b0b1d6836dd0e63686342b70037..dc6ed0135fb8d82937c756c3fb04a7fcb48fe1f4 100644
> --- a/lib/fuse_versionscript
> +++ b/lib/fuse_versionscript
> @@ -227,6 +227,10 @@ FUSE_3.19 {
>  		fuse_session_start_teardown_watchdog;
>  		fuse_session_stop_teardown_watchdog;
>  		fuse_lowlevel_notify_prune;
> +		fuse_daemonize_start;
> +		fuse_daemonize_success;
> +		fuse_daemonize_fail;
> +		fuse_daemonize_is_active;
>  } FUSE_3.18;
>  
>  # Local Variables:
> diff --git a/lib/helper.c b/lib/helper.c
> index 5c13b93a473181f027eba01e0bfefd78875ede3e..35285be19aa0cc390a432d16701b9eefa16ec12a 100644
> --- a/lib/helper.c
> +++ b/lib/helper.c
> @@ -15,6 +15,7 @@
>  #include "fuse_misc.h"
>  #include "fuse_opt.h"
>  #include "fuse_lowlevel.h"
> +#include "fuse_daemonize.h"
>  #include "mount_util.h"
>  
>  #include <stdio.h>
> @@ -352,17 +353,19 @@ int fuse_main_real_versioned(int argc, char *argv[],
>  		goto out1;
>  	}
>  
> +	struct fuse_session *se = fuse_get_session(fuse);
>  	if (fuse_mount(fuse,opts.mountpoint) != 0) {
>  		res = 4;
>  		goto out2;
>  	}
>  
> -	if (fuse_daemonize(opts.foreground) != 0) {
> -		res = 5;
> -		goto out3;
> +	if (!fuse_daemonize_is_active()) {
> +		/* Avoid daemonizing if we are already daemonized by the newer API */
> +		if (fuse_daemonize(opts.foreground) != 0) {
> +			res = 5;
> +			goto out3;
> +		}
>  	}
> -
> -	struct fuse_session *se = fuse_get_session(fuse);
>  	if (fuse_set_signal_handlers(se) != 0) {
>  		res = 6;
>  		goto out3;
> diff --git a/lib/meson.build b/lib/meson.build
> index fcd95741c9d3748fa01d9ec52b417aca66745f26..5bd449ebffe7c9229df904d647d990c6c47f80b5 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -2,7 +2,8 @@ libfuse_sources = ['fuse.c', 'fuse_i.h', 'fuse_loop.c', 'fuse_loop_mt.c',
>                     'fuse_lowlevel.c', 'fuse_misc.h', 'fuse_opt.c',
>                     'fuse_signals.c', 'buffer.c', 'cuse_lowlevel.c',
>                     'helper.c', 'modules/subdir.c', 'mount_util.c',
> -                   'fuse_log.c', 'compat.c', 'util.c', 'util.h' ]
> +                   'fuse_log.c', 'compat.c', 'util.c', 'util.h',
> +                   'fuse_daemonize.c' ]
>  
>  if host_machine.system().startswith('linux')
>     libfuse_sources += [ 'mount.c' ]
> diff --git a/test/test_want_conversion.c b/test/test_want_conversion.c
> index db731edbfe1be8230ae16b422f798603b4a3bb82..48e6dd2dc6084425a0462bba000563c6083160be 100644
> --- a/test/test_want_conversion.c
> +++ b/test/test_want_conversion.c
> @@ -8,6 +8,7 @@
>  #include <inttypes.h>
>  #include <stdbool.h>
>  #include <err.h>
> +#include <errno.h>
>  
>  static void print_conn_info(const char *prefix, struct fuse_conn_info *conn)
>  {
> 
> -- 
> 2.43.0
> 
> 

  parent reply	other threads:[~2026-03-30 17:55 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 [this message]
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
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=20260330175548.GS6202@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=bernd@bsbernd.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