<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>