ddf19c
From b37344c38b866c7e7fb773b4a3172a39306bac7e Mon Sep 17 00:00:00 2001
ddf19c
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
ddf19c
Date: Mon, 27 Jan 2020 19:01:42 +0100
ddf19c
Subject: [PATCH 071/116] virtiofsd: Kill threads when queues are stopped
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-68-dgilbert@redhat.com>
ddf19c
Patchwork-id: 93522
ddf19c
O-Subject: [RHEL-AV-8.2 qemu-kvm PATCH 067/112] virtiofsd: Kill threads when queues are stopped
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
Kill the threads we've started when the queues get stopped.
ddf19c
ddf19c
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
ddf19c
With improvements by:
ddf19c
Signed-off-by: Eryu Guan <eguan@linux.alibaba.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 10477ac47fc57d00a84802ff97c15450cd8021c1)
ddf19c
ddf19c
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ddf19c
---
ddf19c
 tools/virtiofsd/fuse_virtio.c | 51 +++++++++++++++++++++++++++++++++++++------
ddf19c
 1 file changed, 44 insertions(+), 7 deletions(-)
ddf19c
ddf19c
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
ddf19c
index 872968f..7a8774a 100644
ddf19c
--- a/tools/virtiofsd/fuse_virtio.c
ddf19c
+++ b/tools/virtiofsd/fuse_virtio.c
ddf19c
@@ -41,6 +41,7 @@ struct fv_QueueInfo {
ddf19c
     /* Our queue index, corresponds to array position */
ddf19c
     int qidx;
ddf19c
     int kick_fd;
ddf19c
+    int kill_fd; /* For killing the thread */
ddf19c
 
ddf19c
     /* The element for the command currently being processed */
ddf19c
     VuVirtqElement *qe;
ddf19c
@@ -412,14 +413,17 @@ static void *fv_queue_thread(void *opaque)
ddf19c
     fuse_log(FUSE_LOG_INFO, "%s: Start for queue %d kick_fd %d\n", __func__,
ddf19c
              qi->qidx, qi->kick_fd);
ddf19c
     while (1) {
ddf19c
-        struct pollfd pf[1];
ddf19c
+        struct pollfd pf[2];
ddf19c
         pf[0].fd = qi->kick_fd;
ddf19c
         pf[0].events = POLLIN;
ddf19c
         pf[0].revents = 0;
ddf19c
+        pf[1].fd = qi->kill_fd;
ddf19c
+        pf[1].events = POLLIN;
ddf19c
+        pf[1].revents = 0;
ddf19c
 
ddf19c
         fuse_log(FUSE_LOG_DEBUG, "%s: Waiting for Queue %d event\n", __func__,
ddf19c
                  qi->qidx);
ddf19c
-        int poll_res = ppoll(pf, 1, NULL, NULL);
ddf19c
+        int poll_res = ppoll(pf, 2, NULL, NULL);
ddf19c
 
ddf19c
         if (poll_res == -1) {
ddf19c
             if (errno == EINTR) {
ddf19c
@@ -430,12 +434,23 @@ static void *fv_queue_thread(void *opaque)
ddf19c
             fuse_log(FUSE_LOG_ERR, "fv_queue_thread ppoll: %m\n");
ddf19c
             break;
ddf19c
         }
ddf19c
-        assert(poll_res == 1);
ddf19c
+        assert(poll_res >= 1);
ddf19c
         if (pf[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
ddf19c
             fuse_log(FUSE_LOG_ERR, "%s: Unexpected poll revents %x Queue %d\n",
ddf19c
                      __func__, pf[0].revents, qi->qidx);
ddf19c
             break;
ddf19c
         }
ddf19c
+        if (pf[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
ddf19c
+            fuse_log(FUSE_LOG_ERR,
ddf19c
+                     "%s: Unexpected poll revents %x Queue %d killfd\n",
ddf19c
+                     __func__, pf[1].revents, qi->qidx);
ddf19c
+            break;
ddf19c
+        }
ddf19c
+        if (pf[1].revents) {
ddf19c
+            fuse_log(FUSE_LOG_INFO, "%s: kill event on queue %d - quitting\n",
ddf19c
+                     __func__, qi->qidx);
ddf19c
+            break;
ddf19c
+        }
ddf19c
         assert(pf[0].revents & POLLIN);
ddf19c
         fuse_log(FUSE_LOG_DEBUG, "%s: Got queue event on Queue %d\n", __func__,
ddf19c
                  qi->qidx);
ddf19c
@@ -589,6 +604,28 @@ out:
ddf19c
     return NULL;
ddf19c
 }
ddf19c
 
ddf19c
+static void fv_queue_cleanup_thread(struct fv_VuDev *vud, int qidx)
ddf19c
+{
ddf19c
+    int ret;
ddf19c
+    struct fv_QueueInfo *ourqi;
ddf19c
+
ddf19c
+    assert(qidx < vud->nqueues);
ddf19c
+    ourqi = vud->qi[qidx];
ddf19c
+
ddf19c
+    /* Kill the thread */
ddf19c
+    if (eventfd_write(ourqi->kill_fd, 1)) {
ddf19c
+        fuse_log(FUSE_LOG_ERR, "Eventfd_write for queue %d: %s\n",
ddf19c
+                 qidx, strerror(errno));
ddf19c
+    }
ddf19c
+    ret = pthread_join(ourqi->thread, NULL);
ddf19c
+    if (ret) {
ddf19c
+        fuse_log(FUSE_LOG_ERR, "%s: Failed to join thread idx %d err %d\n",
ddf19c
+                 __func__, qidx, ret);
ddf19c
+    }
ddf19c
+    close(ourqi->kill_fd);
ddf19c
+    ourqi->kick_fd = -1;
ddf19c
+}
ddf19c
+
ddf19c
 /* Callback from libvhost-user on start or stop of a queue */
ddf19c
 static void fv_queue_set_started(VuDev *dev, int qidx, bool started)
ddf19c
 {
ddf19c
@@ -633,16 +670,16 @@ static void fv_queue_set_started(VuDev *dev, int qidx, bool started)
ddf19c
         }
ddf19c
         ourqi = vud->qi[qidx];
ddf19c
         ourqi->kick_fd = dev->vq[qidx].kick_fd;
ddf19c
+
ddf19c
+        ourqi->kill_fd = eventfd(0, EFD_CLOEXEC | EFD_SEMAPHORE);
ddf19c
+        assert(ourqi->kill_fd != -1);
ddf19c
         if (pthread_create(&ourqi->thread, NULL, fv_queue_thread, ourqi)) {
ddf19c
             fuse_log(FUSE_LOG_ERR, "%s: Failed to create thread for queue %d\n",
ddf19c
                      __func__, qidx);
ddf19c
             assert(0);
ddf19c
         }
ddf19c
     } else {
ddf19c
-        /* TODO: Kill the thread */
ddf19c
-        assert(qidx < vud->nqueues);
ddf19c
-        ourqi = vud->qi[qidx];
ddf19c
-        ourqi->kick_fd = -1;
ddf19c
+        fv_queue_cleanup_thread(vud, qidx);
ddf19c
     }
ddf19c
 }
ddf19c
 
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c