From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: borntraeger@de.ibm.com, Paolo Bonzini <pbonzini@redhat.com>,
Karl Rister <krister@redhat.com>, Fam Zheng <famz@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH v3 09/10] aio: add .io_poll_begin/end() callbacks
Date: Tue, 22 Nov 2016 16:31:45 +0000 [thread overview]
Message-ID: <1479832306-26440-10-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1479832306-26440-1-git-send-email-stefanha@redhat.com>
The begin and end callbacks can be used to prepare for the polling loop
and clean up when polling stops. Note that they may only be called once
for multiple aio_poll() calls if polling continues to succeed. Once
polling fails the end callback is invoked before aio_poll() resumes file
descriptor monitoring.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
aio-posix.c | 121 ++++++++++++++++++++++++++++++++++++++++++++--------
include/block/aio.h | 20 +++++++++
2 files changed, 123 insertions(+), 18 deletions(-)
diff --git a/aio-posix.c b/aio-posix.c
index 2f76825..9638347 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -30,6 +30,8 @@ struct AioHandler
IOHandler *io_read;
IOHandler *io_write;
AioPollFn *io_poll;
+ IOHandler *io_poll_begin;
+ IOHandler *io_poll_end;
int deleted;
void *opaque;
bool is_external;
@@ -274,6 +276,20 @@ void aio_set_fd_handler(AioContext *ctx,
}
}
+void aio_set_fd_poll(AioContext *ctx, int fd,
+ IOHandler *io_poll_begin,
+ IOHandler *io_poll_end)
+{
+ AioHandler *node = find_aio_handler(ctx, fd);
+
+ if (!node) {
+ return;
+ }
+
+ node->io_poll_begin = io_poll_begin;
+ node->io_poll_end = io_poll_end;
+}
+
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
bool is_external,
@@ -284,9 +300,53 @@ void aio_set_event_notifier(AioContext *ctx,
(IOHandler *)io_read, NULL, io_poll, notifier);
}
+void aio_set_event_notifier_poll(AioContext *ctx,
+ EventNotifier *notifier,
+ EventNotifierHandler *io_poll_begin,
+ EventNotifierHandler *io_poll_end)
+{
+ aio_set_fd_poll(ctx, event_notifier_get_fd(notifier),
+ (IOHandler *)io_poll_begin,
+ (IOHandler *)io_poll_end);
+}
+
+static void poll_set_started(AioContext *ctx, bool started)
+{
+ AioHandler *node;
+
+ if (started == ctx->poll_started) {
+ return;
+ }
+
+ ctx->poll_started = started;
+
+ ctx->walking_handlers++;
+ QLIST_FOREACH(node, &ctx->aio_handlers, node) {
+ IOHandler *fn;
+
+ if (node->deleted) {
+ continue;
+ }
+
+ if (started) {
+ fn = node->io_poll_begin;
+ } else {
+ fn = node->io_poll_end;
+ }
+
+ if (fn) {
+ fn(node->opaque);
+ }
+ }
+ ctx->walking_handlers--;
+}
+
+
bool aio_prepare(AioContext *ctx)
{
- /* TODO run poll handlers? */
+ /* Poll mode cannot be used with glib's event loop, disable it. */
+ poll_set_started(ctx, false);
+
return false;
}
@@ -465,6 +525,37 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns)
return progress;
}
+/* try_poll_mode:
+ * @ctx: the AioContext
+ * @enable: true to attempt polling, false to stop polling
+ *
+ * If enable is true then ctx->notify_me must be non-zero so this function can
+ * detect aio_notify().
+ *
+ * Note that the caller must have incremented ctx->walking_handlers.
+ *
+ * Returns: true if progress was made, false otherwise
+ */
+static bool try_poll_mode(AioContext *ctx, bool enable)
+{
+ if (enable && aio_poll_max_ns && ctx->poll_disable_cnt == 0) {
+ /* See qemu_soonest_timeout() uint64_t hack */
+ int64_t max_ns = MIN((uint64_t)aio_compute_timeout(ctx),
+ (uint64_t)aio_poll_max_ns);
+
+ if (max_ns) {
+ poll_set_started(ctx, true);
+
+ if (run_poll_handlers(ctx, max_ns)) {
+ return true;
+ }
+ }
+ }
+
+ poll_set_started(ctx, false);
+ return false;
+}
+
bool aio_poll(AioContext *ctx, bool blocking)
{
AioHandler *node;
@@ -488,27 +579,21 @@ bool aio_poll(AioContext *ctx, bool blocking)
ctx->walking_handlers++;
- if (blocking && aio_poll_max_ns && ctx->poll_disable_cnt == 0) {
- /* See qemu_soonest_timeout() uint64_t hack */
- int64_t max_ns = MIN((uint64_t)aio_compute_timeout(ctx),
- (uint64_t)aio_poll_max_ns);
+ if (try_poll_mode(ctx, blocking)) {
+ /* Skip file descriptor monitoring if polling succeeded. Just run
+ * BHs and timers.
+ */
- if (max_ns && run_poll_handlers(ctx, max_ns)) {
- /* Skip file descriptor monitoring if polling succeeded. Just run
- * BHs and timers.
- */
+ atomic_sub(&ctx->notify_me, 2);
+ aio_notify_accept(ctx);
- atomic_sub(&ctx->notify_me, 2);
- aio_notify_accept(ctx);
+ ctx->walking_handlers--;
- ctx->walking_handlers--;
+ aio_bh_poll(ctx);
+ timerlistgroup_run_timers(&ctx->tlg);
- aio_bh_poll(ctx);
- timerlistgroup_run_timers(&ctx->tlg);
-
- aio_context_release(ctx);
- return true;
- }
+ aio_context_release(ctx);
+ return true;
}
assert(npfd == 0);
diff --git a/include/block/aio.h b/include/block/aio.h
index 8aa5219..71735c0 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -134,6 +134,9 @@ struct AioContext {
/* Number of AioHandlers without .io_poll() */
int poll_disable_cnt;
+ /* Are we in polling mode or monitoring file descriptors? */
+ bool poll_started;
+
/* epoll(7) state used when built with CONFIG_EPOLL */
int epollfd;
bool epoll_enabled;
@@ -332,6 +335,14 @@ void aio_set_fd_handler(AioContext *ctx,
AioPollFn *io_poll,
void *opaque);
+/* Set polling begin/end callbacks for a file descriptor that has already been
+ * registered with aio_set_fd_handler. Do nothing if the file descriptor is
+ * not registered.
+ */
+void aio_set_fd_poll(AioContext *ctx, int fd,
+ IOHandler *io_poll_begin,
+ IOHandler *io_poll_end);
+
/* Register an event notifier and associated callbacks. Behaves very similarly
* to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks
* will be invoked when using aio_poll().
@@ -345,6 +356,15 @@ void aio_set_event_notifier(AioContext *ctx,
EventNotifierHandler *io_read,
AioPollFn *io_poll);
+/* Set polling begin/end callbacks for an event notifier that has already been
+ * registered with aio_set_event_notifier. Do nothing if the event notifier is
+ * not registered.
+ */
+void aio_set_event_notifier_poll(AioContext *ctx,
+ EventNotifier *notifier,
+ EventNotifierHandler *io_poll_begin,
+ EventNotifierHandler *io_poll_end);
+
/* Return a GSource that lets the main loop poll the file descriptors attached
* to this AioContext.
*/
--
2.7.4
next prev parent reply other threads:[~2016-11-22 16:32 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-22 16:31 [Qemu-devel] [PATCH v3 00/10] aio: experimental virtio-blk polling mode Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 01/10] virtio: add missing vdev->broken check Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 02/10] virtio-blk: suppress virtqueue kick during processing Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 03/10] virtio-scsi: " Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 04/10] aio: add AioPollFn and io_poll() interface Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 05/10] aio: add polling mode to AioContext Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 06/10] virtio: poll virtqueues for new buffers Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 07/10] linux-aio: poll ring for completions Stefan Hajnoczi
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 08/10] virtio: turn vq->notification into a nested counter Stefan Hajnoczi
2016-11-22 16:31 ` Stefan Hajnoczi [this message]
2016-11-22 17:21 ` [Qemu-devel] [PATCH v3 09/10] aio: add .io_poll_begin/end() callbacks Paolo Bonzini
2016-11-23 9:44 ` Stefan Hajnoczi
2016-11-23 10:59 ` Paolo Bonzini
2016-11-22 16:31 ` [Qemu-devel] [PATCH v3 10/10] virtio: disable virtqueue notifications during polling Stefan Hajnoczi
2016-11-22 16:57 ` [Qemu-devel] [PATCH v3 00/10] aio: experimental virtio-blk polling mode no-reply
2016-11-22 17:13 ` Paolo Bonzini
2016-11-22 19:21 ` Christian Borntraeger
2016-11-23 9:51 ` Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1479832306-26440-10-git-send-email-stefanha@redhat.com \
--to=stefanha@redhat.com \
--cc=borntraeger@de.ibm.com \
--cc=famz@redhat.com \
--cc=krister@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).