Blame 0031-virtiofsd-Start-queue-threads.patch

1d442b
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1d442b
Date: Mon, 27 Jan 2020 19:01:00 +0000
1d442b
Subject: [PATCH] virtiofsd: Start queue threads
1d442b
MIME-Version: 1.0
1d442b
Content-Type: text/plain; charset=UTF-8
1d442b
Content-Transfer-Encoding: 8bit
1d442b
1d442b
Start a thread for each queue when we get notified it's been started.
1d442b
1d442b
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442b
fix by:
1d442b
Signed-off-by: Jun Piao <piaojun@huawei.com>
1d442b
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
1d442b
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
1d442b
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442b
(cherry picked from commit e4c55a3c144493b436e40031e2eed61a84eca47b)
1d442b
---
1d442b
 tools/virtiofsd/fuse_virtio.c | 89 +++++++++++++++++++++++++++++++++++
1d442b
 1 file changed, 89 insertions(+)
1d442b
1d442b
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
1d442b
index 4819e56568..2a94bb3cca 100644
1d442b
--- a/tools/virtiofsd/fuse_virtio.c
1d442b
+++ b/tools/virtiofsd/fuse_virtio.c
1d442b
@@ -11,6 +11,7 @@
1d442b
  * See the file COPYING.LIB
1d442b
  */
1d442b
 
1d442b
+#include "qemu/osdep.h"
1d442b
 #include "fuse_virtio.h"
1d442b
 #include "fuse_i.h"
1d442b
 #include "standard-headers/linux/fuse.h"
1d442b
@@ -30,6 +31,15 @@
1d442b
 
1d442b
 #include "contrib/libvhost-user/libvhost-user.h"
1d442b
 
1d442b
+struct fv_QueueInfo {
1d442b
+    pthread_t thread;
1d442b
+    struct fv_VuDev *virtio_dev;
1d442b
+
1d442b
+    /* Our queue index, corresponds to array position */
1d442b
+    int qidx;
1d442b
+    int kick_fd;
1d442b
+};
1d442b
+
1d442b
 /*
1d442b
  * We pass the dev element into libvhost-user
1d442b
  * and then use it to get back to the outer
1d442b
@@ -38,6 +48,13 @@
1d442b
 struct fv_VuDev {
1d442b
     VuDev dev;
1d442b
     struct fuse_session *se;
1d442b
+
1d442b
+    /*
1d442b
+     * The following pair of fields are only accessed in the main
1d442b
+     * virtio_loop
1d442b
+     */
1d442b
+    size_t nqueues;
1d442b
+    struct fv_QueueInfo **qi;
1d442b
 };
1d442b
 
1d442b
 /* From spec */
1d442b
@@ -83,6 +100,75 @@ static void fv_panic(VuDev *dev, const char *err)
1d442b
     exit(EXIT_FAILURE);
1d442b
 }
1d442b
 
1d442b
+static void *fv_queue_thread(void *opaque)
1d442b
+{
1d442b
+    struct fv_QueueInfo *qi = opaque;
1d442b
+    fuse_log(FUSE_LOG_INFO, "%s: Start for queue %d kick_fd %d\n", __func__,
1d442b
+             qi->qidx, qi->kick_fd);
1d442b
+    while (1) {
1d442b
+        /* TODO */
1d442b
+    }
1d442b
+
1d442b
+    return NULL;
1d442b
+}
1d442b
+
1d442b
+/* Callback from libvhost-user on start or stop of a queue */
1d442b
+static void fv_queue_set_started(VuDev *dev, int qidx, bool started)
1d442b
+{
1d442b
+    struct fv_VuDev *vud = container_of(dev, struct fv_VuDev, dev);
1d442b
+    struct fv_QueueInfo *ourqi;
1d442b
+
1d442b
+    fuse_log(FUSE_LOG_INFO, "%s: qidx=%d started=%d\n", __func__, qidx,
1d442b
+             started);
1d442b
+    assert(qidx >= 0);
1d442b
+
1d442b
+    /*
1d442b
+     * Ignore additional request queues for now.  passthrough_ll.c must be
1d442b
+     * audited for thread-safety issues first.  It was written with a
1d442b
+     * well-behaved client in mind and may not protect against all types of
1d442b
+     * races yet.
1d442b
+     */
1d442b
+    if (qidx > 1) {
1d442b
+        fuse_log(FUSE_LOG_ERR,
1d442b
+                 "%s: multiple request queues not yet implemented, please only "
1d442b
+                 "configure 1 request queue\n",
1d442b
+                 __func__);
1d442b
+        exit(EXIT_FAILURE);
1d442b
+    }
1d442b
+
1d442b
+    if (started) {
1d442b
+        /* Fire up a thread to watch this queue */
1d442b
+        if (qidx >= vud->nqueues) {
1d442b
+            vud->qi = realloc(vud->qi, (qidx + 1) * sizeof(vud->qi[0]));
1d442b
+            assert(vud->qi);
1d442b
+            memset(vud->qi + vud->nqueues, 0,
1d442b
+                   sizeof(vud->qi[0]) * (1 + (qidx - vud->nqueues)));
1d442b
+            vud->nqueues = qidx + 1;
1d442b
+        }
1d442b
+        if (!vud->qi[qidx]) {
1d442b
+            vud->qi[qidx] = calloc(sizeof(struct fv_QueueInfo), 1);
1d442b
+            assert(vud->qi[qidx]);
1d442b
+            vud->qi[qidx]->virtio_dev = vud;
1d442b
+            vud->qi[qidx]->qidx = qidx;
1d442b
+        } else {
1d442b
+            /* Shouldn't have been started */
1d442b
+            assert(vud->qi[qidx]->kick_fd == -1);
1d442b
+        }
1d442b
+        ourqi = vud->qi[qidx];
1d442b
+        ourqi->kick_fd = dev->vq[qidx].kick_fd;
1d442b
+        if (pthread_create(&ourqi->thread, NULL, fv_queue_thread, ourqi)) {
1d442b
+            fuse_log(FUSE_LOG_ERR, "%s: Failed to create thread for queue %d\n",
1d442b
+                     __func__, qidx);
1d442b
+            assert(0);
1d442b
+        }
1d442b
+    } else {
1d442b
+        /* TODO: Kill the thread */
1d442b
+        assert(qidx < vud->nqueues);
1d442b
+        ourqi = vud->qi[qidx];
1d442b
+        ourqi->kick_fd = -1;
1d442b
+    }
1d442b
+}
1d442b
+
1d442b
 static bool fv_queue_order(VuDev *dev, int qidx)
1d442b
 {
1d442b
     return false;
1d442b
@@ -92,6 +178,9 @@ static const VuDevIface fv_iface = {
1d442b
     .get_features = fv_get_features,
1d442b
     .set_features = fv_set_features,
1d442b
 
1d442b
+    /* Don't need process message, we've not got any at vhost-user level */
1d442b
+    .queue_set_started = fv_queue_set_started,
1d442b
+
1d442b
     .queue_is_processed_in_order = fv_queue_order,
1d442b
 };
1d442b