static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info *fi) { struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size); (void) ino; buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK; buf.buf[0].fd = fi->fh; buf.buf[0].pos = offset; fuse_reply_data(req, &buf, FUSE_BUF_SPLICE_MOVE); }
static bool read_bulk_cb(struct dfuse_request *request) { struct dfuse_rb *rb = container_of(request, struct dfuse_rb, rb_req); struct dfuse_readx_out *out = request->out; int rc = 0; size_t bytes_read = 0; void *buff = NULL; if (out->err) { DFUSE_TRA_ERROR(rb, "Error from target %d", out->err); rb->failure = true; D_GOTO(out, request->rc = EIO); } DFUSE_REQUEST_RESOLVE(request, out); if (request->rc) D_GOTO(out, 0); if (out->iov_len > 0) { if (out->data.iov_len != out->iov_len) D_GOTO(out, request->rc = EIO); buff = out->data.iov_buf; bytes_read = out->data.iov_len; } else if (out->bulk_len > 0) { bytes_read = out->bulk_len; } out: if (request->rc) { DFUSE_REPLY_ERR(request, request->rc); } else { /* It's not clear without benchmarking which approach is better * here, fuse_reply_buf() is a small wrapper around writev() * which is a much shorter code-path however fuse_reply_data() * attempts to use splice which may well be faster. * * For now it's easy to pick between them, and both of them are * passing valgrind tests. */ if (request->fsh->flags & DFUSE_FUSE_READ_BUF) { rc = fuse_reply_buf(request->req, buff, bytes_read); if (rc != 0) DFUSE_TRA_ERROR(rb, "fuse_reply_buf returned %d:%s", rc, strerror(-rc)); } else { rb->fbuf.buf[0].size = bytes_read; rb->fbuf.buf[0].mem = buff; rc = fuse_reply_data(request->req, &rb->fbuf, 0); if (rc != 0) DFUSE_TRA_ERROR(rb, "fuse_reply_data returned %d:%s", rc, strerror(-rc)); } } dfuse_da_release(rb->pt, rb); return false; }