From: Remy Noel <remy.n...@blade-group.com>
get rid of the delete attribute.
We still need to get rid of the context list lock.
Signed-off-by: Remy Noel <remy.n...@blade-group.com>
---
util/aio-posix.c | 75 ++++++++++++++++++++++--------------------------
util/aio-win32.c | 43 ++++++++++-----------------
2 files changed, 49 insertions(+), 69 deletions(-)
diff --git a/util/aio-posix.c b/util/aio-posix.c
index b34d97292a..83db3f65f4 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -16,6 +16,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "block/block.h"
+#include "qemu/rcu.h"
#include "qemu/rcu_queue.h"
#include "qemu/sockets.h"
#include "qemu/cutils.h"
@@ -26,13 +27,14 @@
struct AioHandler
{
+ struct rcu_head rcu;
+
GPollFD pfd;
IOHandler *io_read;
IOHandler *io_write;
AioPollFn *io_poll;
IOHandler *io_poll_begin;
IOHandler *io_poll_end;
- int deleted;
void *opaque;
bool is_external;
QLIST_ENTRY(AioHandler) node;
@@ -65,19 +67,25 @@ static bool aio_epoll_try_enable(AioContext *ctx)
{
AioHandler *node;
struct epoll_event event;
+ int r = 0;
+
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
- int r;
- if (node->deleted || !node->pfd.events) {
+ if (!node->pfd.events) {
continue;
}
event.events = epoll_events_from_pfd(node->pfd.events);
event.data.ptr = node;
r = epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, node->pfd.fd, &event);
if (r) {
- return false;
+ break;
}
}
+ rcu_read_unlock();
+ if (r) {
+ return false;
+ }
ctx->epoll_enabled = true;
return true;
}
@@ -193,14 +201,13 @@ static AioHandler *find_aio_handler(AioContext *ctx, int
fd)
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->pfd.fd == fd)
- if (!node->deleted)
- return node;
+ return node;
}
return NULL;
}
-static bool aio_remove_fd_handler(AioContext *ctx, AioHandler *node)
+static void aio_remove_fd_handler(AioContext *ctx, AioHandler *node)
{
/* If the GSource is in the process of being destroyed then
* g_source_remove_poll() causes an assertion failure. Skip
@@ -210,19 +217,7 @@ static bool aio_remove_fd_handler(AioContext *ctx,
AioHandler *node)
if (!g_source_is_destroyed(&ctx->source)) {
g_source_remove_poll(&ctx->source, &node->pfd);
}
-
- /* If a read is in progress, just mark the node as deleted */
- if (qemu_lockcnt_count(&ctx->list_lock)) {
- node->deleted = 1;
- node->pfd.revents = 0;
- return false;
- }
- /* Otherwise, delete it for real. We can't just mark it as
- * deleted because deleted nodes are only cleaned up while
- * no one is walking the handlers list.
- */
- QLIST_REMOVE(node, node);
- return true;
+ QLIST_REMOVE_RCU(node, node);
}
void aio_set_fd_handler(AioContext *ctx,
@@ -249,7 +244,8 @@ void aio_set_fd_handler(AioContext *ctx,
qemu_lockcnt_unlock(&ctx->list_lock);
return;
}
- deleted = aio_remove_fd_handler(ctx, node);
+ aio_remove_fd_handler(ctx, node);
+ deleted = true;
poll_disable_change = -!node->io_poll;
} else {
poll_disable_change = !io_poll - (node && !node->io_poll);
@@ -269,7 +265,8 @@ void aio_set_fd_handler(AioContext *ctx,
if (is_new) {
new_node->pfd.fd = fd;
} else {
- deleted = aio_remove_fd_handler(ctx, node);
+ aio_remove_fd_handler(ctx, node);
+ deleted = true;
new_node->pfd = node->pfd;
}
g_source_add_poll(&ctx->source, &new_node->pfd);
@@ -296,7 +293,7 @@ void aio_set_fd_handler(AioContext *ctx,
aio_notify(ctx);
if (deleted) {
- g_free(node);
+ g_free_rcu(node, rcu);
}
}
@@ -345,13 +342,10 @@ static void poll_set_started(AioContext *ctx, bool started)
ctx->poll_started = started;
qemu_lockcnt_inc(&ctx->list_lock);
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
IOHandler *fn;
- if (node->deleted) {
- continue;
- }
-
if (started) {
fn = node->io_poll_begin;
} else {
@@ -362,6 +356,7 @@ static void poll_set_started(AioContext *ctx, bool started)
fn(node->opaque);
}
}
+ rcu_read_unlock();
qemu_lockcnt_dec(&ctx->list_lock);
}
@@ -385,6 +380,7 @@ bool aio_pending(AioContext *ctx)
*/
qemu_lockcnt_inc(&ctx->list_lock);
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
int revents;
@@ -400,6 +396,7 @@ bool aio_pending(AioContext *ctx)
break;
}
}
+ rcu_read_unlock();
qemu_lockcnt_dec(&ctx->list_lock);
return result;
@@ -410,14 +407,14 @@ static bool aio_dispatch_handlers(AioContext *ctx)
AioHandler *node, *tmp;
bool progress = false;
+ rcu_read_lock();
QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) {
int revents;
revents = node->pfd.revents & node->pfd.events;
node->pfd.revents = 0;
- if (!node->deleted &&
- (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
+ if ((revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
aio_node_check(ctx, node->is_external) &&
node->io_read) {
node->io_read(node->opaque);
@@ -427,22 +424,14 @@ static bool aio_dispatch_handlers(AioContext *ctx)
progress = true;
}
}
- if (!node->deleted &&
- (revents & (G_IO_OUT | G_IO_ERR)) &&
+ if ((revents & (G_IO_OUT | G_IO_ERR)) &&
aio_node_check(ctx, node->is_external) &&
node->io_write) {
node->io_write(node->opaque);
progress = true;
}
-
- if (node->deleted) {
- if (qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
- QLIST_REMOVE(node, node);
- g_free(node);
- qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
- }
- }
}
+ rcu_read_unlock();
return progress;
}
@@ -508,8 +497,9 @@ static bool run_poll_handlers_once(AioContext *ctx, int64_t
*timeout)
bool progress = false;
AioHandler *node;
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
- if (!node->deleted && node->io_poll &&
+ if (node->io_poll &&
aio_node_check(ctx, node->is_external) &&
node->io_poll(node->opaque)) {
*timeout = 0;
@@ -520,6 +510,7 @@ static bool run_poll_handlers_once(AioContext *ctx, int64_t
*timeout)
/* Caller handles freeing deleted nodes. Don't do it here. */
}
+ rcu_read_unlock();
return progress;
}
@@ -637,12 +628,14 @@ bool aio_poll(AioContext *ctx, bool blocking)
/* fill pollfds */
if (!aio_epoll_enabled(ctx)) {
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
- if (!node->deleted && node->pfd.events
+ if (node->pfd.events
&& aio_node_check(ctx, node->is_external)) {
add_pollfd(node);
}
}
+ rcu_read_unlock();
}
/* wait until next event */
diff --git a/util/aio-win32.c b/util/aio-win32.c
index 00e38cdd9f..d7c694e5ac 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -29,7 +29,6 @@ struct AioHandler {
IOHandler *io_write;
EventNotifierHandler *io_notify;
GPollFD pfd;
- int deleted;
void *opaque;
bool is_external;
QLIST_ENTRY(AioHandler) node;
@@ -37,18 +36,8 @@ struct AioHandler {
static void aio_remove_fd_handler(AioContext *ctx, AioHandler *node)
{
- /* If aio_poll is in progress, just mark the node as deleted */
- if (qemu_lockcnt_count(&ctx->list_lock)) {
- node->deleted = 1;
- node->pfd.revents = 0;
- } else {
- /* Otherwise, delete it for real. We can't just mark it as
- * deleted because deleted nodes are only cleaned up after
- * releasing the list_lock.
- */
- QLIST_REMOVE(node, node);
- g_free(node);
- }
+ QLIST_REMOVE_RCU(node, node);
+ g_free_rcu(node);
}
void aio_set_fd_handler(AioContext *ctx,
@@ -64,7 +53,7 @@ void aio_set_fd_handler(AioContext *ctx,
qemu_lockcnt_lock(&ctx->list_lock);
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
- if (node->pfd.fd == fd && !node->deleted) {
+ if (node->pfd.fd == fd) {
break;
}
}
@@ -136,7 +125,7 @@ void aio_set_event_notifier(AioContext *ctx,
qemu_lockcnt_lock(&ctx->list_lock);
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
- if (node->e == e && !node->deleted) {
+ if (node->e == e) {
break;
}
}
@@ -188,6 +177,7 @@ bool aio_prepare(AioContext *ctx)
* called while we're walking.
*/
qemu_lockcnt_inc(&ctx->list_lock);
+ rcu_read_lock();
/* fill fd sets */
FD_ZERO(&rfds);
@@ -215,7 +205,7 @@ bool aio_prepare(AioContext *ctx)
}
}
}
-
+ rcu_read_unlock();
qemu_lockcnt_dec(&ctx->list_lock);
return have_select_revents;
}
@@ -230,6 +220,7 @@ bool aio_pending(AioContext *ctx)
* called while we're walking.
*/
qemu_lockcnt_inc(&ctx->list_lock);
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
if (node->pfd.revents && node->io_notify) {
result = true;
@@ -246,6 +237,7 @@ bool aio_pending(AioContext *ctx)
}
}
+ rcu_read_unlock();
qemu_lockcnt_dec(&ctx->list_lock);
return result;
}
@@ -256,6 +248,7 @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE
event)
bool progress = false;
AioHandler *tmp;
+ rcu_read_lock();
/*
* We have to walk very carefully in case aio_set_fd_handler is
* called while we're walking.
@@ -263,8 +256,7 @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE
event)
QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) {
int revents = node->pfd.revents;
- if (!node->deleted &&
- (revents || event_notifier_get_handle(node->e) == event) &&
+ if ((revents || event_notifier_get_handle(node->e) == event) &&
node->io_notify) {
node->pfd.revents = 0;
node->io_notify(node->e);
@@ -275,8 +267,7 @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE
event)
}
}
- if (!node->deleted &&
- (node->io_read || node->io_write)) {
+ if ((node->io_read || node->io_write)) {
node->pfd.revents = 0;
if ((revents & G_IO_IN) && node->io_read) {
node->io_read(node->opaque);
@@ -297,14 +288,8 @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE
event)
}
}
- if (node->deleted) {
- if (qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
- QLIST_REMOVE(node, node);
- g_free(node);
- qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
- }
- }
}
+ rcu_read_unlock();
return progress;
}
@@ -344,12 +329,14 @@ bool aio_poll(AioContext *ctx, bool blocking)
/* fill fd sets */
count = 0;
+ rcu_read_lock();
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
- if (!node->deleted && node->io_notify
+ if (node->io_notify
&& aio_node_check(ctx, node->is_external)) {
events[count++] = event_notifier_get_handle(node->e);
}
}
+ rcu_read_unlock();
first = true;