Add clone_fd to custom IO (#927)
authorlegezywzh <94814730+legezywzh@users.noreply.github.com>
Thu, 18 Apr 2024 09:29:35 +0000 (17:29 +0800)
committerGitHub <noreply@github.com>
Thu, 18 Apr 2024 09:29:35 +0000 (11:29 +0200)
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>
include/fuse_lowlevel.h
lib/fuse_loop_mt.c

index 32f440193e7e232edb3e597bfdac6eab7098acbb..330d40e5416a22189e83f6c36a70f9935512029f 100644 (file)
@@ -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);
 };
 
 /**
index 1d8b7b383ffbc282bc96a05811ed28e0e79b1e5a..70ff8f8a5b3b191c278c6540ce406c767753a103 100644 (file)
@@ -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);