From: Miklos Szeredi Date: Fri, 17 Mar 2006 15:56:05 +0000 (+0000) Subject: fix X-Git-Tag: fuse_2_6_0_pre3~15 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=8d975f6fb3f54c82f295b5e44391637a7c008345;p=qemu-gpiodev%2Flibfuse.git fix --- diff --git a/ChangeLog b/ChangeLog index 7ebda65..1b5d20d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,9 @@ * new exported functions: fuse_session_remove_chan(), fuse_get_session(), fuse_daemonize() + * fuse_chan_recv() may now return a new channel which will be used + to send the reply + 2006-03-16 Miklos Szeredi * Released 2.6.0-pre2 diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index da12152..f06fca3 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1102,12 +1102,12 @@ struct fuse_chan_ops { /** * Hook for receiving a raw request * - * @param ch the channel + * @param ch pointer to the channel * @param buf the buffer to store the request in * @param size the size of the buffer * @return the actual size of the raw request, or -1 on error */ - int (*receive)(struct fuse_chan *ch, char *buf, size_t size); + int (*receive)(struct fuse_chan **chp, char *buf, size_t size); /** * Hook for sending a raw reply @@ -1120,8 +1120,7 @@ struct fuse_chan_ops { * @param count the number of blocks in vector * @return zero on success, -errno on failure */ - int (*send)(struct fuse_chan *ch, const struct iovec iov[], - size_t count); + int (*send)(struct fuse_chan *ch, const struct iovec iov[], size_t count); /** * Destroy the channel @@ -1180,12 +1179,12 @@ struct fuse_session *fuse_chan_session(struct fuse_chan *ch); * * A return value of -ENODEV means, that the filesystem was unmounted * - * @param ch the channel + * @param ch pointer to the channel * @param buf the buffer to store the request in * @param size the size of the buffer * @return the actual size of the raw request, or -errno on error */ -int fuse_chan_recv(struct fuse_chan *ch, char *buf, size_t size); +int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size); /** * Send a raw reply @@ -1218,6 +1217,8 @@ void fuse_chan_destroy(struct fuse_chan *ch); # if FUSE_USE_VERSION == 25 # define fuse_lowlevel_ops fuse_lowlevel_ops_compat25 # define fuse_lowlevel_new fuse_lowlevel_new_compat25 +# define fuse_chan_ops fuse_chan_ops_compat25 +# define fuse_chan_new fuse_chan_new_compat25 # elif FUSE_USE_VERSION == 24 # define fuse_file_info fuse_file_info_compat # define fuse_reply_statfs fuse_reply_statfs_compat diff --git a/include/fuse_lowlevel_compat.h b/include/fuse_lowlevel_compat.h index be4d4d8..c8e7673 100644 --- a/include/fuse_lowlevel_compat.h +++ b/include/fuse_lowlevel_compat.h @@ -88,6 +88,16 @@ struct fuse_session *fuse_lowlevel_new_compat(const char *opts, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata); +#endif /* __FreeBSD__ */ + +struct fuse_chan_ops_compat24 { + int (*receive)(struct fuse_chan *ch, char *buf, size_t size); + int (*send)(struct fuse_chan *ch, const struct iovec iov[], size_t count); + void (*destroy)(struct fuse_chan *ch); +}; + +struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op, + int fd, size_t bufsize, void *data); + int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size); -#endif /* __FreeBSD__ */ diff --git a/lib/fuse.c b/lib/fuse.c index 82e0e44..dc1ab10 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -1881,7 +1881,7 @@ struct fuse_cmd *fuse_read_cmd(struct fuse *f) size_t bufsize = fuse_chan_bufsize(ch); struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize); if (cmd != NULL) { - int res = fuse_chan_recv(ch, cmd->buf, bufsize); + int res = fuse_chan_recv(&ch, cmd->buf, bufsize); if (res <= 0) { free_cmd(cmd); if (res < 0 && res != -EINTR && res != -EAGAIN) diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c index fe7d252..45ff738 100644 --- a/lib/fuse_kern_chan.c +++ b/lib/fuse_kern_chan.c @@ -14,8 +14,10 @@ #include #include -static int fuse_kern_chan_receive(struct fuse_chan *ch, char *buf, size_t size) +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); @@ -50,18 +52,20 @@ static int fuse_kern_chan_receive(struct fuse_chan *ch, char *buf, size_t size) static int fuse_kern_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 (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); + if (res == -1) { + struct fuse_session *se = fuse_chan_session(ch); - assert(se != NULL); + assert(se != NULL); - /* ENOENT means the operation was interrupted */ - if (!fuse_session_exited(se) && err != ENOENT) - perror("fuse: writing device"); - return -err; + /* ENOENT means the operation was interrupted */ + if (!fuse_session_exited(se) && err != ENOENT) + perror("fuse: writing device"); + return -err; + } } return 0; } diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c index 6a6edaa..af85269 100644 --- a/lib/fuse_loop.c +++ b/lib/fuse_loop.c @@ -24,12 +24,13 @@ int fuse_session_loop(struct fuse_session *se) } while (!fuse_session_exited(se)) { - res = fuse_chan_recv(ch, buf, bufsize); + struct fuse_chan *tmpch = ch; + res = fuse_chan_recv(&tmpch, buf, bufsize); if (res == -EINTR) continue; if (res <= 0) break; - fuse_session_process(se, buf, res, ch); + fuse_session_process(se, buf, res, tmpch); } free(buf); diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 16be149..fc8f892 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -24,7 +24,6 @@ struct fuse_worker { int numworker; int numavail; struct fuse_session *se; - struct fuse_chan *ch; struct fuse_chan *prevch; pthread_t threads[FUSE_MAX_WORKERS]; pthread_t main_thread; @@ -32,6 +31,11 @@ struct fuse_worker { int error; }; +struct fuse_wchan { + struct fuse_worker *w; + struct fuse_chan *prevch; +}; + #ifndef USE_UCLIBC #define mutex_init(mut) pthread_mutex_init(mut, NULL) #else @@ -48,11 +52,15 @@ static void mutex_init(pthread_mutex_t *mut) static int fuse_loop_mt_send(struct fuse_chan *ch, const struct iovec iov[], size_t count) { - struct fuse_worker *w = (struct fuse_worker *) fuse_chan_data(ch); - pthread_mutex_lock(&w->lock); - w->numavail ++; - pthread_mutex_unlock(&w->lock); - return fuse_chan_send(w->prevch, iov, count); + int res; + struct fuse_wchan *wchan_data = (struct fuse_wchan *) fuse_chan_data(ch); + pthread_mutex_lock(&wchan_data->w->lock); + wchan_data->w->numavail ++; + pthread_mutex_unlock(&wchan_data->w->lock); + res = fuse_chan_send(wchan_data->prevch, iov, count); + fuse_chan_destroy(ch); + free(wchan_data); + return res; } static int start_thread(struct fuse_worker *w, pthread_t *thread_id); @@ -74,7 +82,11 @@ static void *do_work(void *data) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); while (!fuse_session_exited(w->se)) { - int res = fuse_chan_recv(w->prevch, buf, bufsize); + struct fuse_chan *ch = w->prevch; + struct fuse_chan *wchan; + struct fuse_wchan *wchan_data; + struct fuse_chan_ops cop = { .send = fuse_loop_mt_send }; + int res = fuse_chan_recv(&ch, buf, bufsize); if (res == -EINTR) continue; if (res <= 0) { @@ -105,7 +117,17 @@ static void *do_work(void *data) } } pthread_mutex_unlock(&w->lock); - fuse_session_process(w->se, buf, res, w->ch); + wchan_data = malloc(sizeof(struct fuse_wchan)); + wchan = fuse_chan_new(&cop, -1, fuse_chan_bufsize(ch), wchan_data); + if (!wchan_data || !wchan) { + free(wchan_data); + fuse_session_exit(w->se); + w->error = -1; + break; + } + wchan_data->w = w; + wchan_data->prevch = ch; + fuse_session_process(w->se, buf, res, wchan); } pthread_cleanup_pop(1); @@ -145,10 +167,6 @@ int fuse_session_loop_mt(struct fuse_session *se) int i; int err; struct fuse_worker *w; - struct fuse_chan_ops cop = { - .send = fuse_loop_mt_send, - }; - w = (struct fuse_worker *) malloc(sizeof(struct fuse_worker)); if (w == NULL) { fprintf(stderr, "fuse: failed to allocate worker structure\n"); @@ -157,11 +175,6 @@ int fuse_session_loop_mt(struct fuse_session *se) memset(w, 0, sizeof(struct fuse_worker)); w->se = se; w->prevch = fuse_session_next_chan(se, NULL); - w->ch = fuse_chan_new(&cop, -1, fuse_chan_bufsize(w->prevch), w); - if (w->ch == NULL) { - free(w); - return -1; - } w->error = 0; w->numworker = 1; w->numavail = 1; @@ -179,7 +192,6 @@ int fuse_session_loop_mt(struct fuse_session *se) pthread_join(w->threads[i], NULL); pthread_mutex_destroy(&w->lock); err = w->error; - fuse_chan_destroy(w->ch); free(w); fuse_session_reset(se); return err; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index c6b7db8..7b5cb7b 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -223,6 +223,7 @@ int fuse_reply_err(fuse_req_t req, int err) void fuse_reply_none(fuse_req_t req) { + fuse_chan_send(req->ch, NULL, 0); free_req(req); } diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c index 8a8964f..b0b31dd 100644 --- a/lib/fuse_mt.c +++ b/lib/fuse_mt.c @@ -104,10 +104,10 @@ static int mt_session_exited(void *data) return fuse_session_exited(pd->prevse); } -static int mt_chan_receive(struct fuse_chan *ch, char *buf, size_t size) +static int mt_chan_receive(struct fuse_chan **chp, char *buf, size_t size) { struct fuse_cmd *cmd; - struct procdata *pd = (struct procdata *) fuse_chan_data(ch); + struct procdata *pd = (struct procdata *) fuse_chan_data(*chp); assert(size >= sizeof(cmd)); diff --git a/lib/fuse_session.c b/lib/fuse_session.c index 040645b..6cfd462 100644 --- a/lib/fuse_session.c +++ b/lib/fuse_session.c @@ -7,6 +7,7 @@ */ #include "fuse_lowlevel.h" +#include "fuse_lowlevel_compat.h" #include #include @@ -34,6 +35,8 @@ struct fuse_chan { size_t bufsize; void *data; + + int compat; }; struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data) @@ -116,8 +119,8 @@ int fuse_session_exited(struct fuse_session *se) return se->exited; } -struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, - size_t bufsize, void *data) +struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd, + size_t bufsize, void *data, int compat) { struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch)); if (ch == NULL) { @@ -130,10 +133,24 @@ struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, ch->fd = fd; ch->bufsize = bufsize; ch->data = data; + ch->compat = compat; return ch; } +struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, + size_t bufsize, void *data) +{ + return fuse_chan_new_common(op, fd, bufsize, data, 0); +} + +struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op, + int fd, size_t bufsize, void *data) +{ + return fuse_chan_new_common((struct fuse_chan_ops *) op, fd, bufsize, + data, 24); +} + int fuse_chan_fd(struct fuse_chan *ch) { return ch->fd; @@ -154,14 +171,22 @@ struct fuse_session *fuse_chan_session(struct fuse_chan *ch) return ch->se; } -int fuse_chan_recv(struct fuse_chan *ch, char *buf, size_t size) +int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size) { - return ch->op.receive(ch, buf, size); + struct fuse_chan *ch = *chp; + if (ch->compat) + return ((struct fuse_chan_ops_compat24 *) &ch->op) + ->receive(ch, buf, size); + else + return ch->op.receive(chp, buf, size); } int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size) { - int res = fuse_chan_recv(ch, buf, size); + int res; + + assert(ch->compat); + res = fuse_chan_recv(&ch, buf, size); return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0; } @@ -177,3 +202,7 @@ void fuse_chan_destroy(struct fuse_chan *ch) ch->op.destroy(ch); free(ch); } + +#ifndef __FreeBSD__ +__asm__(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4"); +#endif diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 467d870..147067f 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -83,6 +83,8 @@ FUSE_2.5 { FUSE_2.6 { global: fuse_add_direntry; + fuse_chan_new; + fuse_chan_new_compat24; fuse_daemonize; fuse_get_session; fuse_lowlevel_new;