[Virtio-fs] [PATCH 1/4] virtiofsd: send reply correctly on read failure
Liu Bo
bo.liu at linux.alibaba.com
Tue Apr 16 19:08:55 UTC 2019
From: Eryu Guan <eguan at linux.alibaba.com>
Currently when a lo_read() operation fails, we don't send the failure
back to fuse client, and read(2) operation from guest kernel would hang
on waiting for the reply.
This is easily triggered by a direct read with non-aligned length.
Fix it by detecting preadv(2) error in virtio_send_data_iov(), and
teaching fuse_reply_data() to reply error on error case.
Reviewed-by: Liu Bo <bo.liu at linux.alibaba.com>
Signed-off-by: Eryu Guan <eguan at linux.alibaba.com>
---
contrib/virtiofsd/fuse_lowlevel.c | 4 ++--
contrib/virtiofsd/fuse_virtio.c | 12 +++++++++---
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_lowlevel.c
index 111c6e1..aeb5fe2 100644
--- a/contrib/virtiofsd/fuse_lowlevel.c
+++ b/contrib/virtiofsd/fuse_lowlevel.c
@@ -524,11 +524,11 @@ int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
out.error = 0;
res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv, flags);
- if (res <= 0) {
+ if (res >= 0) {
fuse_free_req(req);
return res;
} else {
- return fuse_reply_err(req, res);
+ return fuse_reply_err(req, -res);
}
}
diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virtio.c
index ca988aa..0b5736d 100644
--- a/contrib/virtiofsd/fuse_virtio.c
+++ b/contrib/virtiofsd/fuse_virtio.c
@@ -333,8 +333,13 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
ret = preadv(buf->buf[0].fd, in_sg_ptr, in_sg_cpy_count, buf->buf[0].pos);
if (se->debug)
- fprintf(stderr, "%s: preadv_res=%d len=%zd\n",
- __func__, ret, len);
+ fprintf(stderr, "%s: preadv_res=%d(%s) len=%zd\n",
+ __func__, ret, strerror(errno), len);
+ if (ret == -1) {
+ ret = -errno;
+ free(in_sg_cpy);
+ goto err;
+ }
if (ret < len && ret) {
if (se->debug)
fprintf(stderr, "%s: ret < len\n", __func__);
@@ -379,7 +384,8 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
vu_queue_notify(&se->virtio_dev->dev, q);
err:
- ch->qi->reply_sent = true;
+ if (!ret)
+ ch->qi->reply_sent = true;
return ret;
}
--
1.8.3.1
More information about the Virtio-fs
mailing list