fix
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 @@
     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 <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_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 @@
     }
 
     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 @@
     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 @@
     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 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 @@
     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 @@
             }
         }
         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 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 @@
     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 @@
         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 @@
 
 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 @@
     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 <stdio.h>
 #include <stdlib.h>
@@ -34,6 +35,8 @@
     size_t bufsize;
 
     void *data;
+
+    int compat;
 };
 
 struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
@@ -116,8 +119,8 @@
         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 @@
     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 @@
     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 @@
         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.6 {
 	global:
 		fuse_add_direntry;
+		fuse_chan_new;
+		fuse_chan_new_compat24;
 		fuse_daemonize;
 		fuse_get_session;
 		fuse_lowlevel_new;