Check if splice/vmsplice are supported
authorMiklos Szeredi <mszeredi@suse.cz>
Fri, 27 May 2011 10:12:31 +0000 (12:12 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Fri, 27 May 2011 10:12:31 +0000 (12:12 +0200)
ChangeLog
configure.in
lib/buffer.c
lib/fuse_lowlevel.c

index f9559cdaeba7592dc42e0ecc0b0681ed9505b688..572425cc3ce7ddb2f4eb093f4ea85f7b789bba6a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2011-05-27  Miklos Szeredi <miklos@szeredi.hu>
+
+       * Check if splice/vmsplice are supported
+
 2011-05-26  Miklos Szeredi <miklos@szeredi.hu>
 
        * Remove -lrt -ldl from fuse.pc for dynamic linking since
index 85ffa354711d111372f87d90ffcd59a0c994e2a7..0e41cca64e9ccb597c08dc7b9d2820aeff979e8b 100644 (file)
@@ -56,7 +56,7 @@ if test "$enable_mtab" = "no"; then
        AC_DEFINE(IGNORE_MTAB, 1, [Don't update /etc/mtab])
 fi
 
-AC_CHECK_FUNCS([fork setxattr fdatasync])
+AC_CHECK_FUNCS([fork setxattr fdatasync splice vmsplice])
 AC_CHECK_MEMBERS([struct stat.st_atim])
 AC_CHECK_MEMBERS([struct stat.st_atimespec])
 
index cb734a3c72763d4bd9612b42c5767d0e6c11adfd..65b0dea69f23405ebd52660a6fb462b5f8e8781a 100644 (file)
@@ -153,6 +153,7 @@ static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off,
        return copied;
 }
 
+#ifdef HAVE_SPLICE
 static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
                               const struct fuse_buf *src, size_t src_off,
                               size_t len, enum fuse_buf_copy_flags flags)
@@ -207,6 +208,16 @@ static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
 
        return copied;
 }
+#else
+static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
+                              const struct fuse_buf *src, size_t src_off,
+                              size_t len, enum fuse_buf_copy_flags flags)
+{
+       (void) flags;
+
+       return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
+}
+#endif
 
 
 static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
index ee8fe2de439503a810eeb1d4b0e2c6b4db63dd12..3cf747d2d3955d926320a676b52b1e808ac2a93d 100644 (file)
@@ -428,6 +428,37 @@ int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
        return send_reply_ok(req, buf, size);
 }
 
+static int fuse_send_data_iov_fallback(struct fuse_ll *f, struct fuse_chan *ch,
+                                      struct iovec *iov, int iov_count,
+                                      struct fuse_bufvec *buf,
+                                      size_t len)
+{
+       struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
+       void *mbuf;
+       int res;
+
+       /* FIXME: Avoid memory copy if none of the buffers contain an fd */
+       res = posix_memalign(&mbuf, pagesize, len);
+       if (res != 0)
+               return res;
+
+       mem_buf.buf[0].mem = mbuf;
+       res = fuse_buf_copy(&mem_buf, buf, 0);
+       if (res < 0) {
+               free(mbuf);
+               return -res;
+       }
+       len = res;
+
+       iov[iov_count].iov_base = mbuf;
+       iov[iov_count].iov_len = len;
+       iov_count++;
+       res = fuse_send_msg(f, ch, iov, iov_count);
+       free(mbuf);
+
+       return res;
+}
+
 struct fuse_ll_pipe {
        size_t size;
        int can_grow;
@@ -441,6 +472,7 @@ static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
        free(llp);
 }
 
+#ifdef HAVE_SPLICE
 static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
 {
        struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key);
@@ -476,6 +508,7 @@ static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
 
        return llp;
 }
+#endif
 
 static void fuse_ll_clear_pipe(struct fuse_ll *f)
 {
@@ -486,6 +519,7 @@ static void fuse_ll_clear_pipe(struct fuse_ll *f)
        }
 }
 
+#if defined(HAVE_SPLICE) && defined(HAVE_VMSPLICE)
 static int read_back(int fd, char *buf, size_t len)
 {
        int res;
@@ -696,31 +730,19 @@ clear_pipe:
        return res;
 
 fallback:
-       {
-               struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
-               void *mbuf;
-
-               res = posix_memalign(&mbuf, pagesize, len);
-               if (res != 0)
-                       return res;
-
-               mem_buf.buf[0].mem = mbuf;
-               res = fuse_buf_copy(&mem_buf, buf, 0);
-               if (res < 0) {
-                       free(mbuf);
-                       return -res;
-               }
-               len = res;
-
-               iov[iov_count].iov_base = mbuf;
-               iov[iov_count].iov_len = len;
-               iov_count++;
-               res = fuse_send_msg(f, ch, iov, iov_count);
-               free(mbuf);
+       return fuse_send_data_iov_fallback(f, ch, iov, iov_count, buf, len);
+}
+#else
+static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch,
+                              struct iovec *iov, int iov_count,
+                              struct fuse_bufvec *buf, unsigned int flags)
+{
+       size_t len = fuse_buf_size(buf);
+       (void) flags;
 
-               return res;
-       }
+       return fuse_send_data_iov_fallback(f, ch, iov, iov_count, buf, len);
 }
+#endif
 
 int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
                    enum fuse_buf_copy_flags flags)
@@ -1710,14 +1732,18 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
        }
 
        if (req->f->conn.proto_minor >= 14) {
+#ifdef HAVE_SPLICE
+#ifdef HAVE_VMSPLICE
                f->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
-               f->conn.capable |= FUSE_CAP_SPLICE_READ;
                if (f->splice_write)
                        f->conn.want |= FUSE_CAP_SPLICE_WRITE;
                if (f->splice_move)
                        f->conn.want |= FUSE_CAP_SPLICE_MOVE;
+#endif
+               f->conn.capable |= FUSE_CAP_SPLICE_READ;
                if (f->splice_read)
                        f->conn.want |= FUSE_CAP_SPLICE_READ;
+#endif
        }
 
        if (f->atomic_o_trunc)
@@ -2424,6 +2450,7 @@ static void fuse_ll_pipe_destructor(void *data)
        fuse_ll_pipe_free(llp);
 }
 
+#ifdef HAVE_SPLICE
 static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
                               struct fuse_chan **chp)
 {
@@ -2521,6 +2548,22 @@ fallback:
 
        return res;
 }
+#else
+static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
+                              struct fuse_chan **chp)
+{
+       (void) se;
+
+       int res = fuse_chan_recv(chp, buf->mem, buf->size);
+       if (res <= 0)
+               return res;
+
+       buf->size = res;
+
+       return res;
+}
+#endif
+
 
 /*
  * always call fuse_lowlevel_new_common() internally, to work around a