From 73cd124d0408649ad20abbdee43fcc723ac2acf2 Mon Sep 17 00:00:00 2001 From: legezywzh <94814730+legezywzh@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:29:35 +0800 Subject: [PATCH] Add clone_fd to custom IO (#927) Define a new clone_fd() helper for fuse_custom_io, users can implement their own clone fd logic. Signed-off-by: Xiaoguang Wang --- include/fuse_lowlevel.h | 1 + lib/fuse_loop_mt.c | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 32f4401..330d40e 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -136,6 +136,7 @@ struct fuse_custom_io { ssize_t (*splice_send)(int fdin, off_t *offin, int fdout, off_t *offout, size_t len, unsigned int flags, void *userdata); + int (*clone_fd)(int master_fd); }; /** diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 1d8b7b3..70ff8f8 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -242,12 +242,11 @@ int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg) return 0; } -static struct fuse_chan *fuse_clone_chan(struct fuse_mt *mt) +static int fuse_clone_chan_fd_default(struct fuse_session *se) { int res; int clonefd; uint32_t masterfd; - struct fuse_chan *newch; const char *devname = "/dev/fuse"; #ifndef O_CLOEXEC @@ -257,20 +256,40 @@ static struct fuse_chan *fuse_clone_chan(struct fuse_mt *mt) if (clonefd == -1) { fuse_log(FUSE_LOG_ERR, "fuse: failed to open %s: %s\n", devname, strerror(errno)); - return NULL; + return -1; } #ifndef O_CLOEXEC fcntl(clonefd, F_SETFD, FD_CLOEXEC); #endif - masterfd = mt->se->fd; + masterfd = se->fd; res = ioctl(clonefd, FUSE_DEV_IOC_CLONE, &masterfd); if (res == -1) { fuse_log(FUSE_LOG_ERR, "fuse: failed to clone device fd: %s\n", strerror(errno)); close(clonefd); - return NULL; + return -1; + } + return clonefd; +} + +static struct fuse_chan *fuse_clone_chan(struct fuse_mt *mt) +{ + int clonefd; + struct fuse_session *se = mt->se; + struct fuse_chan *newch; + + if (se->io != NULL) { + if (se->io->clone_fd != NULL) + clonefd = se->io->clone_fd(se->fd); + else + return NULL; + } else { + clonefd = fuse_clone_chan_fd_default(se); } + if (clonefd < 0) + return NULL; + newch = fuse_chan_new(clonefd); if (newch == NULL) close(clonefd); -- 2.30.2