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