[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 4/4] monitor: add lock to protect mon_fdsets
From: |
Peter Xu |
Subject: |
[Qemu-devel] [PATCH v4 4/4] monitor: add lock to protect mon_fdsets |
Date: |
Wed, 2 May 2018 18:04:22 +0800 |
Similar to previous patch, but introduce a new global big lock for
mon_fdsets. Take it where needed.
Signed-off-by: Peter Xu <address@hidden>
---
monitor.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 53 insertions(+), 11 deletions(-)
diff --git a/monitor.c b/monitor.c
index 6100ad44f8..c0c91cb70e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -263,6 +263,9 @@ typedef struct QMPRequest QMPRequest;
/* Protects mon_list, monitor_event_state. */
static QemuMutex monitor_lock;
+/* Protects mon_fdsets */
+static QemuMutex mon_fdsets_lock;
+
static QTAILQ_HEAD(mon_list, Monitor) mon_list;
static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
static int mon_refcount;
@@ -279,6 +282,16 @@ static QEMUClockType event_clock_type =
QEMU_CLOCK_REALTIME;
static void monitor_command_cb(void *opaque, const char *cmdline,
void *readline_opaque);
+/*
+ * This lock can be used very early, even during param parsing.
+ * Meanwhile it can also be used even at the end of main. Let's keep
+ * it initialized for the whole lifecycle of QEMU.
+ */
+static void __attribute__((constructor)) mon_fdsets_lock_init(void)
+{
+ qemu_mutex_init(&mon_fdsets_lock);
+}
+
/**
* Is @mon a QMP monitor?
*/
@@ -2306,9 +2319,11 @@ static void monitor_fdsets_cleanup(void)
MonFdset *mon_fdset;
MonFdset *mon_fdset_next;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH_SAFE(mon_fdset, &mon_fdsets, next, mon_fdset_next) {
monitor_fdset_cleanup(mon_fdset);
}
+ qemu_mutex_unlock(&mon_fdsets_lock);
}
AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,
@@ -2343,6 +2358,7 @@ void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t
fd, Error **errp)
MonFdsetFd *mon_fdset_fd;
char fd_str[60];
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
if (mon_fdset->id != fdset_id) {
continue;
@@ -2362,10 +2378,12 @@ void qmp_remove_fd(int64_t fdset_id, bool has_fd,
int64_t fd, Error **errp)
goto error;
}
monitor_fdset_cleanup(mon_fdset);
+ qemu_mutex_unlock(&mon_fdsets_lock);
return;
}
error:
+ qemu_mutex_unlock(&mon_fdsets_lock);
if (has_fd) {
snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64 ", fd:%" PRId64,
fdset_id, fd);
@@ -2381,6 +2399,7 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
MonFdsetFd *mon_fdset_fd;
FdsetInfoList *fdset_list = NULL;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info));
FdsetFdInfoList *fdsetfd_list = NULL;
@@ -2410,6 +2429,7 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
fdset_info->next = fdset_list;
fdset_list = fdset_info;
}
+ qemu_mutex_unlock(&mon_fdsets_lock);
return fdset_list;
}
@@ -2422,6 +2442,7 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool
has_fdset_id, int64_t fdset_id,
MonFdsetFd *mon_fdset_fd;
AddfdInfo *fdinfo;
+ qemu_mutex_lock(&mon_fdsets_lock);
if (has_fdset_id) {
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
/* Break if match found or match impossible due to ordering by ID
*/
@@ -2442,6 +2463,7 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool
has_fdset_id, int64_t fdset_id,
if (fdset_id < 0) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id",
"a non-negative value");
+ qemu_mutex_unlock(&mon_fdsets_lock);
return NULL;
}
/* Use specified fdset ID */
@@ -2492,6 +2514,7 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool
has_fdset_id, int64_t fdset_id,
fdinfo->fdset_id = mon_fdset->id;
fdinfo->fd = mon_fdset_fd->fd;
+ qemu_mutex_unlock(&mon_fdsets_lock);
return fdinfo;
}
@@ -2501,7 +2524,9 @@ int monitor_fdset_get_fd(int64_t fdset_id, int flags)
MonFdset *mon_fdset;
MonFdsetFd *mon_fdset_fd;
int mon_fd_flags;
+ int ret = -1;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
if (mon_fdset->id != fdset_id) {
continue;
@@ -2509,49 +2534,62 @@ int monitor_fdset_get_fd(int64_t fdset_id, int flags)
QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL);
if (mon_fd_flags == -1) {
- return -1;
+ goto out;
}
if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) {
- return mon_fdset_fd->fd;
+ ret = mon_fdset_fd->fd;
+ goto out;
}
}
errno = EACCES;
- return -1;
+ break;
}
-#endif
-
+out:
+ qemu_mutex_unlock(&mon_fdsets_lock);
+ return ret;
+#else
errno = ENOENT;
return -1;
+#endif
}
int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
{
MonFdset *mon_fdset;
MonFdsetFd *mon_fdset_fd_dup;
+ int ret = -1;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
if (mon_fdset->id != fdset_id) {
continue;
}
QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
if (mon_fdset_fd_dup->fd == dup_fd) {
- return -1;
+ ret = -1;
+ goto out;
}
}
mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup));
mon_fdset_fd_dup->fd = dup_fd;
QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next);
- return 0;
+ ret = 0;
+ break;
}
- return -1;
+
+out:
+ qemu_mutex_unlock(&mon_fdsets_lock);
+ return ret;
}
static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
{
MonFdset *mon_fdset;
MonFdsetFd *mon_fdset_fd_dup;
+ int ret = -1;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
if (mon_fdset_fd_dup->fd == dup_fd) {
@@ -2560,14 +2598,18 @@ static int monitor_fdset_dup_fd_find_remove(int dup_fd,
bool remove)
if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
monitor_fdset_cleanup(mon_fdset);
}
- return -1;
+ ret = -1;
+ goto out;
} else {
- return mon_fdset->id;
+ ret = mon_fdset->id;
+ goto out;
}
}
}
}
- return -1;
+out:
+ qemu_mutex_unlock(&mon_fdsets_lock);
+ return ret;
}
int monitor_fdset_dup_fd_find(int dup_fd)
--
2.14.3