|
|
1d442b |
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
|
|
1d442b |
Date: Mon, 27 Jan 2020 19:01:42 +0000
|
|
|
1d442b |
Subject: [PATCH] virtiofsd: Kill threads when queues are stopped
|
|
|
1d442b |
MIME-Version: 1.0
|
|
|
1d442b |
Content-Type: text/plain; charset=UTF-8
|
|
|
1d442b |
Content-Transfer-Encoding: 8bit
|
|
|
1d442b |
|
|
|
1d442b |
Kill the threads we've started when the queues get stopped.
|
|
|
1d442b |
|
|
|
1d442b |
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
1d442b |
With improvements by:
|
|
|
1d442b |
Signed-off-by: Eryu Guan <eguan@linux.alibaba.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 10477ac47fc57d00a84802ff97c15450cd8021c1)
|
|
|
1d442b |
---
|
|
|
1d442b |
tools/virtiofsd/fuse_virtio.c | 51 ++++++++++++++++++++++++++++++-----
|
|
|
1d442b |
1 file changed, 44 insertions(+), 7 deletions(-)
|
|
|
1d442b |
|
|
|
1d442b |
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
|
|
|
1d442b |
index 872968f2c8..7a8774a3ee 100644
|
|
|
1d442b |
--- a/tools/virtiofsd/fuse_virtio.c
|
|
|
1d442b |
+++ b/tools/virtiofsd/fuse_virtio.c
|
|
|
1d442b |
@@ -41,6 +41,7 @@ struct fv_QueueInfo {
|
|
|
1d442b |
/* Our queue index, corresponds to array position */
|
|
|
1d442b |
int qidx;
|
|
|
1d442b |
int kick_fd;
|
|
|
1d442b |
+ int kill_fd; /* For killing the thread */
|
|
|
1d442b |
|
|
|
1d442b |
/* The element for the command currently being processed */
|
|
|
1d442b |
VuVirtqElement *qe;
|
|
|
1d442b |
@@ -412,14 +413,17 @@ static void *fv_queue_thread(void *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 |
- struct pollfd pf[1];
|
|
|
1d442b |
+ struct pollfd pf[2];
|
|
|
1d442b |
pf[0].fd = qi->kick_fd;
|
|
|
1d442b |
pf[0].events = POLLIN;
|
|
|
1d442b |
pf[0].revents = 0;
|
|
|
1d442b |
+ pf[1].fd = qi->kill_fd;
|
|
|
1d442b |
+ pf[1].events = POLLIN;
|
|
|
1d442b |
+ pf[1].revents = 0;
|
|
|
1d442b |
|
|
|
1d442b |
fuse_log(FUSE_LOG_DEBUG, "%s: Waiting for Queue %d event\n", __func__,
|
|
|
1d442b |
qi->qidx);
|
|
|
1d442b |
- int poll_res = ppoll(pf, 1, NULL, NULL);
|
|
|
1d442b |
+ int poll_res = ppoll(pf, 2, NULL, NULL);
|
|
|
1d442b |
|
|
|
1d442b |
if (poll_res == -1) {
|
|
|
1d442b |
if (errno == EINTR) {
|
|
|
1d442b |
@@ -430,12 +434,23 @@ static void *fv_queue_thread(void *opaque)
|
|
|
1d442b |
fuse_log(FUSE_LOG_ERR, "fv_queue_thread ppoll: %m\n");
|
|
|
1d442b |
break;
|
|
|
1d442b |
}
|
|
|
1d442b |
- assert(poll_res == 1);
|
|
|
1d442b |
+ assert(poll_res >= 1);
|
|
|
1d442b |
if (pf[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
|
|
1d442b |
fuse_log(FUSE_LOG_ERR, "%s: Unexpected poll revents %x Queue %d\n",
|
|
|
1d442b |
__func__, pf[0].revents, qi->qidx);
|
|
|
1d442b |
break;
|
|
|
1d442b |
}
|
|
|
1d442b |
+ if (pf[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
|
|
1d442b |
+ fuse_log(FUSE_LOG_ERR,
|
|
|
1d442b |
+ "%s: Unexpected poll revents %x Queue %d killfd\n",
|
|
|
1d442b |
+ __func__, pf[1].revents, qi->qidx);
|
|
|
1d442b |
+ break;
|
|
|
1d442b |
+ }
|
|
|
1d442b |
+ if (pf[1].revents) {
|
|
|
1d442b |
+ fuse_log(FUSE_LOG_INFO, "%s: kill event on queue %d - quitting\n",
|
|
|
1d442b |
+ __func__, qi->qidx);
|
|
|
1d442b |
+ break;
|
|
|
1d442b |
+ }
|
|
|
1d442b |
assert(pf[0].revents & POLLIN);
|
|
|
1d442b |
fuse_log(FUSE_LOG_DEBUG, "%s: Got queue event on Queue %d\n", __func__,
|
|
|
1d442b |
qi->qidx);
|
|
|
1d442b |
@@ -589,6 +604,28 @@ out:
|
|
|
1d442b |
return NULL;
|
|
|
1d442b |
}
|
|
|
1d442b |
|
|
|
1d442b |
+static void fv_queue_cleanup_thread(struct fv_VuDev *vud, int qidx)
|
|
|
1d442b |
+{
|
|
|
1d442b |
+ int ret;
|
|
|
1d442b |
+ struct fv_QueueInfo *ourqi;
|
|
|
1d442b |
+
|
|
|
1d442b |
+ assert(qidx < vud->nqueues);
|
|
|
1d442b |
+ ourqi = vud->qi[qidx];
|
|
|
1d442b |
+
|
|
|
1d442b |
+ /* Kill the thread */
|
|
|
1d442b |
+ if (eventfd_write(ourqi->kill_fd, 1)) {
|
|
|
1d442b |
+ fuse_log(FUSE_LOG_ERR, "Eventfd_write for queue %d: %s\n",
|
|
|
1d442b |
+ qidx, strerror(errno));
|
|
|
1d442b |
+ }
|
|
|
1d442b |
+ ret = pthread_join(ourqi->thread, NULL);
|
|
|
1d442b |
+ if (ret) {
|
|
|
1d442b |
+ fuse_log(FUSE_LOG_ERR, "%s: Failed to join thread idx %d err %d\n",
|
|
|
1d442b |
+ __func__, qidx, ret);
|
|
|
1d442b |
+ }
|
|
|
1d442b |
+ close(ourqi->kill_fd);
|
|
|
1d442b |
+ ourqi->kick_fd = -1;
|
|
|
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 |
@@ -633,16 +670,16 @@ static void fv_queue_set_started(VuDev *dev, int qidx, bool started)
|
|
|
1d442b |
}
|
|
|
1d442b |
ourqi = vud->qi[qidx];
|
|
|
1d442b |
ourqi->kick_fd = dev->vq[qidx].kick_fd;
|
|
|
1d442b |
+
|
|
|
1d442b |
+ ourqi->kill_fd = eventfd(0, EFD_CLOEXEC | EFD_SEMAPHORE);
|
|
|
1d442b |
+ assert(ourqi->kill_fd != -1);
|
|
|
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 |
+ fv_queue_cleanup_thread(vud, qidx);
|
|
|
1d442b |
}
|
|
|
1d442b |
}
|
|
|
1d442b |
|