1d442bb
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1d442bb
Date: Mon, 27 Jan 2020 19:01:04 +0000
1d442bb
Subject: [PATCH] virtiofsd: Keep track of replies
1d442bb
MIME-Version: 1.0
1d442bb
Content-Type: text/plain; charset=UTF-8
1d442bb
Content-Transfer-Encoding: 8bit
1d442bb
1d442bb
Keep track of whether we sent a reply to a request; this is a bit
1d442bb
paranoid but it means:
1d442bb
  a) We should always recycle an element even if there was an error
1d442bb
     in the request
1d442bb
  b) Never try and send two replies on one queue element
1d442bb
1d442bb
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442bb
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
1d442bb
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442bb
(cherry picked from commit 2f65e69a7f22da8d20c747f34f339ebb40a0634f)
1d442bb
---
1d442bb
 tools/virtiofsd/fuse_virtio.c | 23 ++++++++++++++++++++---
1d442bb
 1 file changed, 20 insertions(+), 3 deletions(-)
1d442bb
1d442bb
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
1d442bb
index 05d0e29f12..f1adeb6345 100644
1d442bb
--- a/tools/virtiofsd/fuse_virtio.c
1d442bb
+++ b/tools/virtiofsd/fuse_virtio.c
1d442bb
@@ -44,6 +44,7 @@ struct fv_QueueInfo {
1d442bb
 
1d442bb
     /* The element for the command currently being processed */
1d442bb
     VuVirtqElement *qe;
1d442bb
+    bool reply_sent;
1d442bb
 };
1d442bb
 
1d442bb
 /*
1d442bb
@@ -178,6 +179,7 @@ int virtio_send_msg(struct fuse_session *se, struct fuse_chan *ch,
1d442bb
 {
1d442bb
     VuVirtqElement *elem;
1d442bb
     VuVirtq *q;
1d442bb
+    int ret = 0;
1d442bb
 
1d442bb
     assert(count >= 1);
1d442bb
     assert(iov[0].iov_len >= sizeof(struct fuse_out_header));
1d442bb
@@ -191,6 +193,7 @@ int virtio_send_msg(struct fuse_session *se, struct fuse_chan *ch,
1d442bb
     assert(out->unique);
1d442bb
     /* For virtio we always have ch */
1d442bb
     assert(ch);
1d442bb
+    assert(!ch->qi->reply_sent);
1d442bb
     elem = ch->qi->qe;
1d442bb
     q = &ch->qi->virtio_dev->dev.vq[ch->qi->qidx];
1d442bb
 
1d442bb
@@ -208,19 +211,23 @@ int virtio_send_msg(struct fuse_session *se, struct fuse_chan *ch,
1d442bb
     if (in_len < sizeof(struct fuse_out_header)) {
1d442bb
         fuse_log(FUSE_LOG_ERR, "%s: elem %d too short for out_header\n",
1d442bb
                  __func__, elem->index);
1d442bb
-        return -E2BIG;
1d442bb
+        ret = -E2BIG;
1d442bb
+        goto err;
1d442bb
     }
1d442bb
     if (in_len < tosend_len) {
1d442bb
         fuse_log(FUSE_LOG_ERR, "%s: elem %d too small for data len %zd\n",
1d442bb
                  __func__, elem->index, tosend_len);
1d442bb
-        return -E2BIG;
1d442bb
+        ret = -E2BIG;
1d442bb
+        goto err;
1d442bb
     }
1d442bb
 
1d442bb
     copy_iov(iov, count, in_sg, in_num, tosend_len);
1d442bb
     vu_queue_push(&se->virtio_dev->dev, q, elem, tosend_len);
1d442bb
     vu_queue_notify(&se->virtio_dev->dev, q);
1d442bb
+    ch->qi->reply_sent = true;
1d442bb
 
1d442bb
-    return 0;
1d442bb
+err:
1d442bb
+    return ret;
1d442bb
 }
1d442bb
 
1d442bb
 /* Thread function for individual queues, created when a queue is 'started' */
1d442bb
@@ -296,6 +303,9 @@ static void *fv_queue_thread(void *opaque)
1d442bb
                 break;
1d442bb
             }
1d442bb
 
1d442bb
+            qi->qe = elem;
1d442bb
+            qi->reply_sent = false;
1d442bb
+
1d442bb
             if (!fbuf.mem) {
1d442bb
                 fbuf.mem = malloc(se->bufsize);
1d442bb
                 assert(fbuf.mem);
1d442bb
@@ -331,6 +341,13 @@ static void *fv_queue_thread(void *opaque)
1d442bb
             /* TODO: Add checks for fuse_session_exited */
1d442bb
             fuse_session_process_buf_int(se, &fbuf, &ch);
1d442bb
 
1d442bb
+            if (!qi->reply_sent) {
1d442bb
+                fuse_log(FUSE_LOG_DEBUG, "%s: elem %d no reply sent\n",
1d442bb
+                         __func__, elem->index);
1d442bb
+                /* I think we've still got to recycle the element */
1d442bb
+                vu_queue_push(dev, q, elem, 0);
1d442bb
+                vu_queue_notify(dev, q);
1d442bb
+            }
1d442bb
             qi->qe = NULL;
1d442bb
             free(elem);
1d442bb
             elem = NULL;