From: Miklos Szeredi Date: Fri, 27 May 2011 10:12:31 +0000 (+0200) Subject: Check if splice/vmsplice are supported X-Git-Tag: fuse_2_9_0~33 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=4a9f6ab4805d805ac3b437c89d11ae365a0370f3;p=qemu-gpiodev%2Flibfuse.git Check if splice/vmsplice are supported --- diff --git a/ChangeLog b/ChangeLog index f9559cd..572425c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-27 Miklos Szeredi + + * Check if splice/vmsplice are supported + 2011-05-26 Miklos Szeredi * Remove -lrt -ldl from fuse.pc for dynamic linking since diff --git a/configure.in b/configure.in index 85ffa35..0e41cca 100644 --- a/configure.in +++ b/configure.in @@ -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]) diff --git a/lib/buffer.c b/lib/buffer.c index cb734a3..65b0dea 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -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, diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index ee8fe2d..3cf747d 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -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