aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlegezywzh <94814730+legezywzh@users.noreply.github.com>2024-04-18 17:29:35 +0800
committerGitHub <noreply@github.com>2024-04-18 11:29:35 +0200
commit73cd124d0408649ad20abbdee43fcc723ac2acf2 (patch)
tree6cb749124212e906edd26d411db8e48650fe5706
parent080077369e7fa740da7d9813e6766c308e4e555c (diff)
downloadlibfuse-73cd124d0408649ad20abbdee43fcc723ac2acf2.tar.gz
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 <lege.wang@jaguarmicro.com>
-rw-r--r--include/fuse_lowlevel.h1
-rw-r--r--lib/fuse_loop_mt.c29
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);