<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le lun. 4 mars 2024, 11:36, David Marchand <<a href="mailto:david.marchand@redhat.com" target="_blank" rel="noreferrer">david.marchand@redhat.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Maxime Coquelin <<a href="mailto:maxime.coquelin@redhat.com" rel="noreferrer noreferrer" target="_blank">maxime.coquelin@redhat.com</a>><br>
<br>
VDUSE_DESTROY_DEVICE ioctl can fail because the device's<br>
chardev is not released despite close syscall having been<br>
called. It happens because the events handler thread is<br>
still polling the file descriptor.<br>
<br>
fdset_pipe_notify() is not enough because it does not<br>
ensure the notification has been handled by the event<br>
thread, it just returns once the notification is sent.<br>
<br>
To fix this, this patch introduces a synchronization<br>
mechanism based on pthread's condition, so that<br>
fdset_pipe_notify_sync() only returns once the pipe's<br>
read callback has been executed.<br>
<br>
Fixes: 51d018fdac4e ("vhost: add VDUSE events handler")<br>
Cc: <a href="mailto:stable@dpdk.org" rel="noreferrer noreferrer" target="_blank">stable@dpdk.org</a><br>
<br>
Signed-off-by: Maxime Coquelin <<a href="mailto:maxime.coquelin@redhat.com" rel="noreferrer noreferrer" target="_blank">maxime.coquelin@redhat.com</a>><br>
Signed-off-by: David Marchand <<a href="mailto:david.marchand@redhat.com" rel="noreferrer noreferrer" target="_blank">david.marchand@redhat.com</a>><br>
---<br>
Changes since v1:<br>
- sync'd only when in VDUSE destruction path,<br>
- added explicit init of sync_mutex,<br>
<br>
---<br>
 lib/vhost/fd_man.c | 23 +++++++++++++++++++++--<br>
 lib/vhost/fd_man.h |  6 ++++++<br>
 lib/vhost/socket.c |  1 +<br>
 lib/vhost/vduse.c  |  3 ++-<br>
 4 files changed, 30 insertions(+), 3 deletions(-)<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Reviewed-by: Maxime Coquelin <<a href="mailto:maxime.coquelin@redhat.com" target="_blank" rel="noreferrer">maxime.coquelin@redhat.com</a>></div><div dir="auto"><br></div><div dir="auto">Thanks for improving the patch,</div><div dir="auto">Maxime</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c<br>
index 79a8d2c006..481e6b900a 100644<br>
--- a/lib/vhost/fd_man.c<br>
+++ b/lib/vhost/fd_man.c<br>
@@ -309,10 +309,11 @@ fdset_event_dispatch(void *arg)<br>
 }<br>
<br>
 static void<br>
-fdset_pipe_read_cb(int readfd, void *dat __rte_unused,<br>
+fdset_pipe_read_cb(int readfd, void *dat,<br>
                   int *remove __rte_unused)<br>
 {<br>
        char charbuf[16];<br>
+       struct fdset *fdset = dat;<br>
        int r = read(readfd, charbuf, sizeof(charbuf));<br>
        /*<br>
         * Just an optimization, we don't care if read() failed<br>
@@ -320,6 +321,11 @@ fdset_pipe_read_cb(int readfd, void *dat __rte_unused,<br>
         * compiler happy<br>
         */<br>
        RTE_SET_USED(r);<br>
+<br>
+       pthread_mutex_lock(&fdset->sync_mutex);<br>
+       fdset->sync = true;<br>
+       pthread_cond_broadcast(&fdset->sync_cond);<br>
+       pthread_mutex_unlock(&fdset->sync_mutex);<br>
 }<br>
<br>
 void<br>
@@ -342,7 +348,7 @@ fdset_pipe_init(struct fdset *fdset)<br>
        }<br>
<br>
        ret = fdset_add(fdset, fdset->u.readfd,<br>
-                       fdset_pipe_read_cb, NULL, NULL);<br>
+                       fdset_pipe_read_cb, NULL, fdset);<br>
<br>
        if (ret < 0) {<br>
                VHOST_FDMAN_LOG(ERR,<br>
@@ -366,5 +372,18 @@ fdset_pipe_notify(struct fdset *fdset)<br>
         * compiler happy<br>
         */<br>
        RTE_SET_USED(r);<br>
+}<br>
+<br>
+void<br>
+fdset_pipe_notify_sync(struct fdset *fdset)<br>
+{<br>
+       pthread_mutex_lock(&fdset->sync_mutex);<br>
+<br>
+       fdset->sync = false;<br>
+       fdset_pipe_notify(fdset);<br>
+<br>
+       while (!fdset->sync)<br>
+               pthread_cond_wait(&fdset->sync_cond, &fdset->sync_mutex);<br>
<br>
+       pthread_mutex_unlock(&fdset->sync_mutex);<br>
 }<br>
diff --git a/lib/vhost/fd_man.h b/lib/vhost/fd_man.h<br>
index 6315904c8e..7816fb11ac 100644<br>
--- a/lib/vhost/fd_man.h<br>
+++ b/lib/vhost/fd_man.h<br>
@@ -6,6 +6,7 @@<br>
 #define _FD_MAN_H_<br>
 #include <pthread.h><br>
 #include <poll.h><br>
+#include <stdbool.h><br>
<br>
 #define MAX_FDS 1024<br>
<br>
@@ -35,6 +36,10 @@ struct fdset {<br>
                        int writefd;<br>
                };<br>
        } u;<br>
+<br>
+       pthread_mutex_t sync_mutex;<br>
+       pthread_cond_t sync_cond;<br>
+       bool sync;<br>
 };<br>
<br>
<br>
@@ -53,5 +58,6 @@ int fdset_pipe_init(struct fdset *fdset);<br>
 void fdset_pipe_uninit(struct fdset *fdset);<br>
<br>
 void fdset_pipe_notify(struct fdset *fdset);<br>
+void fdset_pipe_notify_sync(struct fdset *fdset);<br>
<br>
 #endif<br>
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c<br>
index a2fdac30a4..96b3ab5595 100644<br>
--- a/lib/vhost/socket.c<br>
+++ b/lib/vhost/socket.c<br>
@@ -93,6 +93,7 @@ static struct vhost_user vhost_user = {<br>
                .fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },<br>
                .fd_mutex = PTHREAD_MUTEX_INITIALIZER,<br>
                .fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,<br>
+               .sync_mutex = PTHREAD_MUTEX_INITIALIZER,<br>
                .num = 0<br>
        },<br>
        .vsocket_cnt = 0,<br>
diff --git a/lib/vhost/vduse.c b/lib/vhost/vduse.c<br>
index d462428d2c..e0c6991b69 100644<br>
--- a/lib/vhost/vduse.c<br>
+++ b/lib/vhost/vduse.c<br>
@@ -36,6 +36,7 @@ static struct vduse vduse = {<br>
                .fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },<br>
                .fd_mutex = PTHREAD_MUTEX_INITIALIZER,<br>
                .fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,<br>
+               .sync_mutex = PTHREAD_MUTEX_INITIALIZER,<br>
                .num = 0<br>
        },<br>
 };<br>
@@ -618,7 +619,7 @@ vduse_device_destroy(const char *path)<br>
        vduse_device_stop(dev);<br>
<br>
        fdset_del(&vduse.fdset, dev->vduse_dev_fd);<br>
-       fdset_pipe_notify(&vduse.fdset);<br>
+       fdset_pipe_notify_sync(&vduse.fdset);<br>
<br>
        if (dev->vduse_dev_fd >= 0) {<br>
                close(dev->vduse_dev_fd);<br>
-- <br>
2.43.0<br>
<br>
</blockquote></div></div></div>