diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/cuse_lowlevel.c | 6 | ||||
-rw-r--r-- | lib/fuse.c | 23 | ||||
-rw-r--r-- | lib/fuse_i.h | 45 | ||||
-rw-r--r-- | lib/fuse_kern_chan.c | 95 | ||||
-rw-r--r-- | lib/fuse_loop.c | 23 | ||||
-rwxr-xr-x | lib/fuse_loop_mt.c | 30 | ||||
-rwxr-xr-x | lib/fuse_lowlevel.c | 161 | ||||
-rw-r--r-- | lib/fuse_session.c | 114 | ||||
-rw-r--r-- | lib/fuse_versionscript | 11 | ||||
-rw-r--r-- | lib/helper.c | 14 | ||||
-rw-r--r-- | lib/mount.c | 18 | ||||
-rw-r--r-- | lib/mount_bsd.c | 9 |
13 files changed, 204 insertions, 346 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 8ec234a..e1dbfa2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,7 +20,6 @@ endif libfuse_la_SOURCES = \ fuse.c \ fuse_i.h \ - fuse_kern_chan.c \ fuse_loop.c \ fuse_loop_mt.c \ fuse_lowlevel.c \ diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c index c51a78e..b094bd1 100644 --- a/lib/cuse_lowlevel.c +++ b/lib/cuse_lowlevel.c @@ -174,7 +174,7 @@ struct fuse_session *cuse_lowlevel_new(struct fuse_args *args, free(cd); return NULL; } - ll = se->data; + ll = se->f; ll->cuse_data = cd; return se; @@ -199,7 +199,7 @@ void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) struct cuse_init_out outarg; struct fuse_ll *f = req->f; struct cuse_data *cd = f->cuse_data; - size_t bufsize = fuse_chan_bufsize(req->ch); + size_t bufsize = f->bufsize; struct cuse_lowlevel_ops *clop = req_clop(req); (void) nodeid; @@ -312,7 +312,7 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[], goto err_se; } - ch = fuse_kern_chan_new(fd); + ch = fuse_chan_new(fd); if (!ch) { close(fd); goto err_se; @@ -4021,27 +4021,18 @@ static int fuse_session_loop_remember(struct fuse *f) int res = 0; struct timespec now; time_t next_clean; - struct fuse_chan *ch = fuse_session_next_chan(se, NULL); - size_t bufsize = fuse_chan_bufsize(ch); - char *buf = (char *) malloc(bufsize); + struct fuse_chan *ch = fuse_session_chan(se); struct pollfd fds = { .fd = fuse_chan_fd(ch), .events = POLLIN }; - - if (!buf) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - return -1; - } + struct fuse_buf fbuf = { + .mem = NULL, + }; curr_time(&now); next_clean = now.tv_sec; while (!fuse_session_exited(se)) { - struct fuse_chan *tmpch = ch; - struct fuse_buf fbuf = { - .mem = buf, - .size = bufsize, - }; unsigned timeout; curr_time(&now); @@ -4057,14 +4048,14 @@ static int fuse_session_loop_remember(struct fuse *f) else break; } else if (res > 0) { - res = fuse_session_receive_buf(se, &fbuf, &tmpch); + res = fuse_session_receive_buf(se, &fbuf, ch); if (res == -EINTR) continue; if (res <= 0) break; - fuse_session_process_buf(se, &fbuf, tmpch); + fuse_session_process_buf(se, &fbuf, ch); } else { timeout = fuse_clean_cache(f); curr_time(&now); @@ -4072,7 +4063,7 @@ static int fuse_session_loop_remember(struct fuse *f) } } - free(buf); + free(fbuf.mem); fuse_session_reset(se); return res < 0 ? -1 : 0; } diff --git a/lib/fuse_i.h b/lib/fuse_i.h index ffcf062..5823743 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -13,21 +13,20 @@ struct fuse_chan; struct fuse_ll; struct fuse_session { - struct fuse_session_ops op; - - int (*receive_buf)(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp); - - void (*process_buf)(void *data, const struct fuse_buf *buf, - struct fuse_chan *ch); - - void *data; + struct fuse_ll *f; volatile int exited; struct fuse_chan *ch; }; +struct fuse_chan { + struct fuse_session *se; + + int fd; +}; + + struct fuse_req { struct fuse_ll *f; uint64_t unique; @@ -89,9 +88,35 @@ struct fuse_ll { int broken_splice_nonblock; uint64_t notify_ctr; struct fuse_notify_req notify_list; + size_t bufsize; }; -struct fuse_chan *fuse_kern_chan_new(int fd); +int fuse_chan_clearfd(struct fuse_chan *ch); +void fuse_chan_close(struct fuse_chan *ch); + +/** + * Create a new session + * + * @return new session object, or NULL on failure + */ +struct fuse_session *fuse_session_new(void); + +/** + * Create a new channel + * + * @param op channel operations + * @param fd file descriptor of the channel + * @return the new channel object, or NULL on failure + */ +struct fuse_chan *fuse_chan_new(int fd); + +/** + * Query the session to which this channel is assigned + * + * @param ch the channel + * @return the session, or NULL if the channel is not assigned + */ +struct fuse_session *fuse_chan_session(struct fuse_chan *ch); void fuse_kern_unmount(const char *mountpoint, int fd); int fuse_kern_mount(const char *mountpoint, struct fuse_args *args); diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c deleted file mode 100644 index 5f77bbf..0000000 --- a/lib/fuse_kern_chan.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - FUSE: Filesystem in Userspace - Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> - - This program can be distributed under the terms of the GNU LGPLv2. - See the file COPYING.LIB -*/ - -#include "fuse_lowlevel.h" -#include "fuse_kernel.h" -#include "fuse_i.h" - -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <assert.h> - -static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf, - size_t size) -{ - struct fuse_chan *ch = *chp; - int err; - ssize_t res; - struct fuse_session *se = fuse_chan_session(ch); - assert(se != NULL); - -restart: - res = read(fuse_chan_fd(ch), buf, size); - err = errno; - - if (fuse_session_exited(se)) - return 0; - if (res == -1) { - /* ENOENT means the operation was interrupted, it's safe - to restart */ - if (err == ENOENT) - goto restart; - - if (err == ENODEV) { - fuse_session_exit(se); - return 0; - } - /* Errors occurring during normal operation: EINTR (read - interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem - umounted) */ - if (err != EINTR && err != EAGAIN) - perror("fuse: reading device"); - return -err; - } - if ((size_t) res < sizeof(struct fuse_in_header)) { - fprintf(stderr, "short read on fuse device\n"); - return -EIO; - } - return res; -} - -static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[], - size_t count) -{ - if (iov) { - ssize_t res = writev(fuse_chan_fd(ch), iov, count); - int err = errno; - - if (res == -1) { - struct fuse_session *se = fuse_chan_session(ch); - - assert(se != NULL); - - /* ENOENT means the operation was interrupted */ - if (!fuse_session_exited(se) && err != ENOENT) - perror("fuse: writing device"); - return -err; - } - } - return 0; -} - -static void fuse_kern_chan_destroy(struct fuse_chan *ch) -{ - close(fuse_chan_fd(ch)); -} - -#define MIN_BUFSIZE 0x21000 - -struct fuse_chan *fuse_kern_chan_new(int fd) -{ - struct fuse_chan_ops op = { - .receive = fuse_kern_chan_receive, - .send = fuse_kern_chan_send, - .destroy = fuse_kern_chan_destroy, - }; - size_t bufsize = getpagesize() + 0x1000; - bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize; - return fuse_chan_new(&op, fd, bufsize, NULL); -} diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c index b7b4ca4..7ddf2f9 100644 --- a/lib/fuse_loop.c +++ b/lib/fuse_loop.c @@ -15,32 +15,23 @@ int fuse_session_loop(struct fuse_session *se) { int res = 0; - struct fuse_chan *ch = fuse_session_next_chan(se, NULL); - size_t bufsize = fuse_chan_bufsize(ch); - char *buf = (char *) malloc(bufsize); - if (!buf) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - return -1; - } + struct fuse_chan *ch = fuse_session_chan(se); + struct fuse_buf fbuf = { + .mem = NULL, + }; while (!fuse_session_exited(se)) { - struct fuse_chan *tmpch = ch; - struct fuse_buf fbuf = { - .mem = buf, - .size = bufsize, - }; - - res = fuse_session_receive_buf(se, &fbuf, &tmpch); + res = fuse_session_receive_buf(se, &fbuf, ch); if (res == -EINTR) continue; if (res <= 0) break; - fuse_session_process_buf(se, &fbuf, tmpch); + fuse_session_process_buf(se, &fbuf, ch); } - free(buf); + free(fbuf.mem); fuse_session_reset(se); return res < 0 ? -1 : 0; } diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 82e3001..b146d73 100755 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -28,7 +28,7 @@ struct fuse_worker { struct fuse_worker *next; pthread_t thread_id; size_t bufsize; - char *buf; + struct fuse_buf fbuf; struct fuse_mt *mt; }; @@ -70,15 +70,10 @@ static void *fuse_do_work(void *data) while (!fuse_session_exited(mt->se)) { int isforget = 0; - struct fuse_chan *ch = mt->prevch; - struct fuse_buf fbuf = { - .mem = w->buf, - .size = w->bufsize, - }; int res; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - res = fuse_session_receive_buf(mt->se, &fbuf, &ch); + res = fuse_session_receive_buf(mt->se, &w->fbuf, mt->prevch); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); if (res == -EINTR) continue; @@ -100,8 +95,8 @@ static void *fuse_do_work(void *data) * This disgusting hack is needed so that zillions of threads * are not created on a burst of FORGET messages */ - if (!(fbuf.flags & FUSE_BUF_IS_FD)) { - struct fuse_in_header *in = fbuf.mem; + if (!(w->fbuf.flags & FUSE_BUF_IS_FD)) { + struct fuse_in_header *in = w->fbuf.mem; if (in->opcode == FUSE_FORGET || in->opcode == FUSE_BATCH_FORGET) @@ -114,7 +109,7 @@ static void *fuse_do_work(void *data) fuse_loop_start_thread(mt); pthread_mutex_unlock(&mt->lock); - fuse_session_process_buf(mt->se, &fbuf, ch); + fuse_session_process_buf(mt->se, &w->fbuf, mt->prevch); pthread_mutex_lock(&mt->lock); if (!isforget) @@ -130,7 +125,7 @@ static void *fuse_do_work(void *data) pthread_mutex_unlock(&mt->lock); pthread_detach(w->thread_id); - free(w->buf); + free(w->fbuf.mem); free(w); return NULL; } @@ -184,18 +179,11 @@ static int fuse_loop_start_thread(struct fuse_mt *mt) return -1; } memset(w, 0, sizeof(struct fuse_worker)); - w->bufsize = fuse_chan_bufsize(mt->prevch); - w->buf = malloc(w->bufsize); + w->fbuf.mem = NULL; w->mt = mt; - if (!w->buf) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - free(w); - return -1; - } res = fuse_start_thread(&w->thread_id, fuse_do_work, w); if (res == -1) { - free(w->buf); free(w); return -1; } @@ -212,7 +200,7 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w) pthread_mutex_lock(&mt->lock); list_del_worker(w); pthread_mutex_unlock(&mt->lock); - free(w->buf); + free(w->fbuf.mem); free(w); } @@ -224,7 +212,7 @@ int fuse_session_loop_mt(struct fuse_session *se) memset(&mt, 0, sizeof(struct fuse_mt)); mt.se = se; - mt.prevch = fuse_session_next_chan(se, NULL); + mt.prevch = fuse_session_chan(se); mt.error = 0; mt.numworker = 0; mt.numavail = 0; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 45cd5f3..76cb7b7 100755 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -153,6 +153,80 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_ll *f) return req; } +static int fuse_chan_recv(struct fuse_session *se, struct fuse_buf *buf, + struct fuse_chan *ch) +{ + struct fuse_ll *f = se->f; + int err; + ssize_t res; + + if (!buf->mem) { + buf->mem = malloc(f->bufsize); + if (!buf->mem) { + fprintf(stderr, + "fuse: failed to allocate read buffer\n"); + return -ENOMEM; + } + } + +restart: + res = read(fuse_chan_fd(ch), buf->mem, f->bufsize); + err = errno; + + if (fuse_session_exited(se)) + return 0; + if (res == -1) { + /* ENOENT means the operation was interrupted, it's safe + to restart */ + if (err == ENOENT) + goto restart; + + if (err == ENODEV) { + fuse_session_exit(se); + return 0; + } + /* Errors occurring during normal operation: EINTR (read + interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem + umounted) */ + if (err != EINTR && err != EAGAIN) + perror("fuse: reading device"); + return -err; + } + if ((size_t) res < sizeof(struct fuse_in_header)) { + fprintf(stderr, "short read on fuse device\n"); + return -EIO; + } + + buf->size = res; + + return res; +} + +static int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], + size_t count) +{ + ssize_t res = writev(fuse_chan_fd(ch), iov, count); + int err = errno; + + if (res == -1) { + struct fuse_session *se = fuse_chan_session(ch); + + assert(se != NULL); + + /* ENOENT means the operation was interrupted */ + if (!fuse_session_exited(se) && err != ENOENT) + perror("fuse: writing device"); + return -err; + } + + return 0; +} + +void fuse_chan_close(struct fuse_chan *ch) +{ + close(fuse_chan_fd(ch)); +} + static int fuse_send_msg(struct fuse_ll *f, struct fuse_chan *ch, struct iovec *iov, int count) @@ -301,8 +375,6 @@ int fuse_reply_err(fuse_req_t req, int err) void fuse_reply_none(fuse_req_t req) { - if (req->ch) - fuse_chan_send(req->ch, NULL, 0); fuse_free_req(req); } @@ -1787,7 +1859,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) struct fuse_init_in *arg = (struct fuse_init_in *) inarg; struct fuse_init_out outarg; struct fuse_ll *f = req->f; - size_t bufsize = fuse_chan_bufsize(req->ch); + size_t bufsize = f->bufsize; (void) nodeid; if (f->debug) { @@ -2062,7 +2134,7 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2086,7 +2158,7 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2113,7 +2185,7 @@ int fuse_lowlevel_notify_delete(struct fuse_chan *ch, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2147,7 +2219,7 @@ int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2229,7 +2301,7 @@ int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2374,10 +2446,10 @@ static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst, return 0; } -static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, - struct fuse_chan *ch) +void fuse_session_process_buf(struct fuse_session *se, + const struct fuse_buf *buf, struct fuse_chan *ch) { - struct fuse_ll *f = (struct fuse_ll *) data; + struct fuse_ll *f = se->f; const size_t write_header_size = sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in); struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 }; @@ -2513,17 +2585,6 @@ clear_pipe: goto out_free; } -static void fuse_ll_process(void *data, const char *buf, size_t len, - struct fuse_chan *ch) -{ - struct fuse_buf fbuf = { - .mem = (void *) buf, - .size = len, - }; - - fuse_ll_process_buf(data, &fbuf, ch); -} - enum { KEY_HELP, KEY_VERSION, @@ -2616,9 +2677,8 @@ static int fuse_ll_opt_proc(void *data, const char *arg, int key, return -1; } -static void fuse_ll_destroy(void *data) +static void fuse_ll_destroy(struct fuse_ll *f) { - struct fuse_ll *f = (struct fuse_ll *) data; struct fuse_ll_pipe *llp; if (f->got_init && !f->got_destroy) { @@ -2634,6 +2694,15 @@ static void fuse_ll_destroy(void *data) free(f); } +void fuse_session_destroy(struct fuse_session *se) +{ + fuse_ll_destroy(se->f); + if (se->ch != NULL) + fuse_chan_destroy(se->ch); + free(se); +} + + static void fuse_ll_pipe_destructor(void *data) { struct fuse_ll_pipe *llp = data; @@ -2641,12 +2710,11 @@ static void fuse_ll_pipe_destructor(void *data) } #ifdef HAVE_SPLICE -static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp) +int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, + struct fuse_chan *ch) { - struct fuse_chan *ch = *chp; - struct fuse_ll *f = fuse_session_data(se); - size_t bufsize = buf->size; + struct fuse_ll *f = se->f; + size_t bufsize = buf->size = f->bufsize; struct fuse_ll_pipe *llp; struct fuse_buf tmpbuf; int err; @@ -2730,30 +2798,17 @@ static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, return res; fallback: - res = fuse_chan_recv(chp, buf->mem, bufsize); - if (res <= 0) - return res; - - buf->size = res; - - return res; + return fuse_chan_recv(se, buf, ch); } #else -static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp) +int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, + struct fuse_chan *ch) { - (void) se; - - int res = fuse_chan_recv(chp, buf->mem, buf->size); - if (res <= 0) - return res; - - buf->size = res; - - return res; + return fuse_chan_recv(se, buf, ch); } #endif +#define MIN_BUFSIZE 0x21000 struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, @@ -2762,10 +2817,6 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, int err; struct fuse_ll *f; struct fuse_session *se; - struct fuse_session_ops sop = { - .process = fuse_ll_process, - .destroy = fuse_ll_destroy, - }; if (sizeof(struct fuse_lowlevel_ops) < op_size) { fprintf(stderr, "fuse: warning: library too old, some operations may not work\n"); @@ -2782,6 +2833,9 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, f->conn.max_write = UINT_MAX; f->conn.max_readahead = UINT_MAX; f->atomic_o_trunc = 0; + f->bufsize = getpagesize() + 0x1000; + f->bufsize = f->bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : f->bufsize; + list_init_req(&f->list); list_init_req(&f->interrupts); list_init_nreq(&f->notify_list); @@ -2805,12 +2859,11 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, f->owner = getuid(); f->userdata = userdata; - se = fuse_session_new(&sop, f); + se = fuse_session_new(); if (!se) goto out_key_destroy; - se->receive_buf = fuse_ll_receive_buf; - se->process_buf = fuse_ll_process_buf; + se->f = f; return se; diff --git a/lib/fuse_session.c b/lib/fuse_session.c index ccd11c3..c030d68 100644 --- a/lib/fuse_session.c +++ b/lib/fuse_session.c @@ -15,29 +15,15 @@ #include <assert.h> #include <errno.h> -struct fuse_chan { - struct fuse_chan_ops op; - struct fuse_session *se; - - int fd; - - size_t bufsize; - - void *data; -}; - -struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data) +struct fuse_session *fuse_session_new(void) { struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se)); if (se == NULL) { fprintf(stderr, "fuse: failed to allocate session\n"); return NULL; } - memset(se, 0, sizeof(*se)); - se->op = *op; - se->data = data; return se; } @@ -60,88 +46,34 @@ void fuse_session_remove_chan(struct fuse_chan *ch) } } -struct fuse_chan *fuse_session_next_chan(struct fuse_session *se, - struct fuse_chan *ch) -{ - assert(ch == NULL || ch == se->ch); - if (ch == NULL) - return se->ch; - else - return NULL; -} - -void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, - struct fuse_chan *ch) +struct fuse_chan *fuse_session_chan(struct fuse_session *se) { - se->op.process(se->data, buf, len, ch); + return se->ch; } -void fuse_session_process_buf(struct fuse_session *se, - const struct fuse_buf *buf, struct fuse_chan *ch) +int fuse_chan_clearfd(struct fuse_chan *ch) { - if (se->process_buf) { - se->process_buf(se->data, buf, ch); - } else { - assert(!(buf->flags & FUSE_BUF_IS_FD)); - fuse_session_process(se->data, buf->mem, buf->size, ch); - } -} - -int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp) -{ - int res; - - if (se->receive_buf) { - res = se->receive_buf(se, buf, chp); - } else { - res = fuse_chan_recv(chp, buf->mem, buf->size); - if (res > 0) - buf->size = res; - } - - return res; -} - - -void fuse_session_destroy(struct fuse_session *se) -{ - if (se->op.destroy) - se->op.destroy(se->data); - if (se->ch != NULL) - fuse_chan_destroy(se->ch); - free(se); + int fd = ch->fd; + ch->fd = -1; + return fd; } void fuse_session_exit(struct fuse_session *se) { - if (se->op.exit) - se->op.exit(se->data, 1); se->exited = 1; } void fuse_session_reset(struct fuse_session *se) { - if (se->op.exit) - se->op.exit(se->data, 0); se->exited = 0; } int fuse_session_exited(struct fuse_session *se) { - if (se->op.exited) - return se->op.exited(se->data); - else - return se->exited; + return se->exited; } -void *fuse_session_data(struct fuse_session *se) -{ - return se->data; -} - -struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, - size_t bufsize, void *data) +struct fuse_chan *fuse_chan_new(int fd) { struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch)); if (ch == NULL) { @@ -150,10 +82,7 @@ struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, } memset(ch, 0, sizeof(*ch)); - ch->op = *op; ch->fd = fd; - ch->bufsize = bufsize; - ch->data = data; return ch; } @@ -163,37 +92,14 @@ int fuse_chan_fd(struct fuse_chan *ch) return ch->fd; } -size_t fuse_chan_bufsize(struct fuse_chan *ch) -{ - return ch->bufsize; -} - -void *fuse_chan_data(struct fuse_chan *ch) -{ - return ch->data; -} - struct fuse_session *fuse_chan_session(struct fuse_chan *ch) { return ch->se; } -int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size) -{ - struct fuse_chan *ch = *chp; - - return ch->op.receive(chp, buf, size); -} - -int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count) -{ - return ch->op.send(ch, iov, count); -} - void fuse_chan_destroy(struct fuse_chan *ch) { fuse_session_remove_chan(ch); - if (ch->op.destroy) - ch->op.destroy(ch); + fuse_chan_close(ch); free(ch); } diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index cfff5de..08dafbd 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -4,12 +4,8 @@ FUSE_3.0 { fuse_exit; fuse_loop; fuse_loop_mt; - fuse_chan_bufsize; - fuse_chan_data; fuse_chan_destroy; fuse_chan_fd; - fuse_chan_send; - fuse_chan_session; fuse_reply_attr; fuse_reply_buf; fuse_reply_entry; @@ -25,9 +21,7 @@ FUSE_3.0 { fuse_session_exited; fuse_session_loop; fuse_session_loop_mt; - fuse_session_new; - fuse_session_next_chan; - fuse_session_process; + fuse_session_chan; fuse_session_reset; fuse_opt_parse; fuse_opt_add_opt; @@ -42,8 +36,6 @@ FUSE_3.0 { fuse_set_signal_handlers; fuse_add_direntry; fuse_add_direntry_plus; - fuse_chan_new; - fuse_chan_recv; fuse_daemonize; fuse_get_session; fuse_interrupted; @@ -118,7 +110,6 @@ FUSE_3.0 { fuse_reply_poll; fuse_req_ctx; fuse_req_getgroups; - fuse_session_data; fuse_buf_copy; fuse_buf_size; fuse_fs_read_buf; diff --git a/lib/helper.c b/lib/helper.c index 8ee66df..204bb22 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -235,7 +235,7 @@ struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) if (fd == -1) return NULL; - ch = fuse_kern_chan_new(fd); + ch = fuse_chan_new(fd); if (!ch) fuse_kern_unmount(mountpoint, fd); @@ -244,10 +244,12 @@ struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) { - int fd = ch ? fuse_chan_fd(ch) : -1; - fuse_kern_unmount(mountpoint, fd); - if (ch) - fuse_chan_destroy(ch); + if (mountpoint) { + int fd = ch ? fuse_chan_clearfd(ch) : -1; + fuse_kern_unmount(mountpoint, fd); + if (ch) + fuse_chan_destroy(ch); + } } static struct fuse *fuse_setup(int argc, char *argv[], @@ -297,7 +299,7 @@ err_free: static void fuse_teardown(struct fuse *fuse, char *mountpoint) { struct fuse_session *se = fuse_get_session(fuse); - struct fuse_chan *ch = fuse_session_next_chan(se, NULL); + struct fuse_chan *ch = fuse_session_chan(se); fuse_remove_signal_handlers(se); fuse_unmount(mountpoint, ch); fuse_destroy(fuse); diff --git a/lib/mount.c b/lib/mount.c index 4f74841..cb5d190 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -294,23 +294,24 @@ void fuse_kern_unmount(const char *mountpoint, int fd) int res; int pid; - if (!mountpoint) - return; - if (fd != -1) { struct pollfd pfd; pfd.fd = fd; pfd.events = 0; res = poll(&pfd, 1, 0); + + /* Need to close file descriptor, otherwise synchronous umount + would recurse into filesystem, and deadlock. + + Caller expects fuse_kern_unmount to close the fd, so close it + anyway. */ + close(fd); + /* If file poll returns POLLERR on the device file descriptor, then the filesystem is already unmounted */ if (res == 1 && (pfd.revents & POLLERR)) return; - - /* Need to close file descriptor, otherwise synchronous umount - would recurse into filesystem, and deadlock */ - close(fd); } if (geteuid() == 0) { @@ -403,6 +404,9 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, waitpid(pid, NULL, 0); /* bury zombie */ } + if (rv >= 0) + fcntl(rv, F_SETFD, FD_CLOEXEC); + return rv; } diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c index 9ee74fb..36c5a2b 100644 --- a/lib/mount_bsd.c +++ b/lib/mount_bsd.c @@ -228,18 +228,21 @@ void fuse_kern_unmount(const char *mountpoint, int fd) (void)mountpoint; if (fstat(fd, &sbuf) == -1) - return; + goto out; devname_r(sbuf.st_rdev, S_IFCHR, dev, 128); if (strncmp(dev, "fuse", 4)) - return; + goto out; strtol(dev + 4, &ep, 10); if (*ep != '\0') - return; + goto out; do_unmount(dev, fd); + +out: + close(fd); } /* Check if kernel is doing init in background */ |