fix
authorMiklos Szeredi <miklos@szeredi.hu>
Fri, 17 Mar 2006 15:56:05 +0000 (15:56 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Fri, 17 Mar 2006 15:56:05 +0000 (15:56 +0000)
ChangeLog
include/fuse_lowlevel.h
include/fuse_lowlevel_compat.h
lib/fuse.c
lib/fuse_kern_chan.c
lib/fuse_loop.c
lib/fuse_loop_mt.c
lib/fuse_lowlevel.c
lib/fuse_mt.c
lib/fuse_session.c
lib/fuse_versionscript

index 7ebda651e335f65be5851ff0928e36f55dc432c8..1b5d20db5f40f28ef8f11078ee8677987df5885e 100644 (file)
--- 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 <miklos@szeredi.hu>
 
        * Released 2.6.0-pre2
index da12152946408f99014e2412b9e3454d3a3e5ef2..f06fca3218a8886cd848fedcf69fd8c6f9c5d4a5 100644 (file)
@@ -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
index be4d4d80cf77ca736abad6a6052cce233c7148de..c8e767323383031465e555679f723c8a0810cfe7 100644 (file)
@@ -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__ */
index 82e0e442d0a5a19db6bc66a65f7bcf6f34aa6527..dc1ab1016c08ea379a1b65c5a823023830e59a04 100644 (file)
@@ -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)
index fe7d252730d626d04f9df9e3161c2f164dc1b713..45ff738b845f671bc23164ce515628c943cf7cca 100644 (file)
 #include <unistd.h>
 #include <assert.h>
 
-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;
 }
index 6a6edaac9c6c196a7089dd5f8cf0d2f480c0b416..af852697bda5f4db53845ef4978759d318711f48 100644 (file)
@@ -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);
index 16be149d3de8af68448e44887e9a634d841199f8..fc8f892f02955e9cc33baa5fccf8b7afc4d2f6d4 100644 (file)
@@ -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;
index c6b7db87d06eba8f80be541272b78de349dfb3d5..7b5cb7b06a84d757f7a01dc3f0e43ca33166a431 100644 (file)
@@ -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);
 }
 
index 8a8964f5cd40860e04f8c2bac8190d9802a7a22e..b0b31dd307990b07efcbad033f669879219826c4 100644 (file)
@@ -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));
 
index 040645b75354db017eb9813a209008593c6ed64e..6cfd462b37d4f5904cfd398bd64f07bd866110e2 100644 (file)
@@ -7,6 +7,7 @@
 */
 
 #include "fuse_lowlevel.h"
+#include "fuse_lowlevel_compat.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -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
index 467d8709ee5b0cd0ad09055cb7f035d9c448df8e..147067fff8307c89d9f669e95496acb5cf05510f 100644 (file)
@@ -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;