* [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane @ 2015-07-29 4:42 Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier Fam Zheng ` (13 more replies) 0 siblings, 14 replies; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block v2: Switch to disable/enable model. [Paolo] Most existing nested aio_poll()'s in block layer are inconsiderate of dispatching potential new r/w requests from ioeventfds and nbd exports, which might result in responsiveness issues (e.g. bdrv_drain_all will not return when new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot enforce atomicity due to aio_poll in bdrv_drain_all). Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] and nested AioContext (patches not posted to qemu-devel). This approach is based on the idea proposed by Paolo Bonzini. The original idea is introducing "aio_context_disable_client / aio_context_enable_client to filter AioContext handlers according to the "client", e.g. AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a client (type)." After this series, block layer aio_poll() will only process those "protocol" fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other aio_poll()'s keep unchanged. The biggest advantage over approaches [1] and [2] is, no change is needed in virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to coroutines. The windows implementation is not tested except for compiling. [1]: https://lists.gnu.org/archive/html/qemu-block/2015-05/msg00800.html [2]: http://lists.nongnu.org/archive/html/qemu-block/2015-06/msg00027.html Fam Zheng (11): aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier aio: Save type to AioHandler block: Mark fd handlers as "protocol" nbd: Mark fd handlers client type as "nbd server" aio: Mark ctx->notifier's client type as "context" dataplane: Mark host notifiers' client type as "dataplane" aio-posix: introduce aio_{disable,enable}_clients aio-win32: Implement aio_{disable,enable}_clients block: Introduce bdrv_aio_poll block: Replace nested aio_poll with bdrv_aio_poll block: Only poll block layer fds in bdrv_aio_poll aio-posix.c | 23 ++++++++++++++-- aio-win32.c | 22 +++++++++++++++- async.c | 3 ++- block.c | 2 +- block/curl.c | 16 +++++++----- block/io.c | 28 +++++++++++++------- block/iscsi.c | 9 +++---- block/linux-aio.c | 5 ++-- block/nbd-client.c | 10 ++++--- block/nfs.c | 19 ++++++-------- block/qed-table.c | 8 +++--- block/sheepdog.c | 32 +++++++++++++++-------- block/ssh.c | 5 ++-- block/win32-aio.c | 5 ++-- blockjob.c | 2 +- hw/block/dataplane/virtio-blk.c | 6 +++-- hw/scsi/virtio-scsi-dataplane.c | 24 +++++++++++------ include/block/aio.h | 33 +++++++++++++++++++++++ include/block/block.h | 2 ++ nbd.c | 4 ++- qemu-img.c | 2 +- qemu-io-cmds.c | 4 +-- tests/test-aio.c | 58 +++++++++++++++++++++++------------------ 23 files changed, 219 insertions(+), 103 deletions(-) -- 2.4.3 ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 13:50 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 02/11] aio: Save type to AioHandler Fam Zheng ` (12 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block The parameter is added but not used. The callers are converted with following coccinelle semantic patch: @@ expression E1, E2, E3, E4, E5; @@ ( -aio_set_event_notifier(E1, E2, E3) +aio_set_event_notifier(E1, E2, AIO_CLIENT_UNSPECIFIED, E3) | -aio_set_fd_handler(E1, E2, E3, E4, E5) +aio_set_fd_handler(E1, E2, AIO_CLIENT_UNSPECIFIED, E3, E4, E5) ) Signed-off-by: Fam Zheng <famz@redhat.com> --- aio-posix.c | 4 ++- aio-win32.c | 2 ++ async.c | 3 ++- block/curl.c | 14 +++++----- block/iscsi.c | 9 +++---- block/linux-aio.c | 5 ++-- block/nbd-client.c | 10 ++++--- block/nfs.c | 17 +++++------- block/sheepdog.c | 32 +++++++++++++++-------- block/ssh.c | 5 ++-- block/win32-aio.c | 5 ++-- hw/block/dataplane/virtio-blk.c | 6 +++-- hw/scsi/virtio-scsi-dataplane.c | 24 +++++++++++------ include/block/aio.h | 5 ++++ nbd.c | 4 ++- tests/test-aio.c | 58 +++++++++++++++++++++++------------------ 16 files changed, 122 insertions(+), 81 deletions(-) diff --git a/aio-posix.c b/aio-posix.c index d477033..56f2bce 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -43,6 +43,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd) void aio_set_fd_handler(AioContext *ctx, int fd, + int type, IOHandler *io_read, IOHandler *io_write, void *opaque) @@ -92,10 +93,11 @@ void aio_set_fd_handler(AioContext *ctx, void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, + int type, EventNotifierHandler *io_read) { aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), - (IOHandler *)io_read, NULL, notifier); + type, (IOHandler *)io_read, NULL, notifier); } bool aio_prepare(AioContext *ctx) diff --git a/aio-win32.c b/aio-win32.c index 50a6867..90e7a4b 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -33,6 +33,7 @@ struct AioHandler { void aio_set_fd_handler(AioContext *ctx, int fd, + int type, IOHandler *io_read, IOHandler *io_write, void *opaque) @@ -98,6 +99,7 @@ void aio_set_fd_handler(AioContext *ctx, void aio_set_event_notifier(AioContext *ctx, EventNotifier *e, + int type, EventNotifierHandler *io_notify) { AioHandler *node; diff --git a/async.c b/async.c index 9a98a74..43f9425 100644 --- a/async.c +++ b/async.c @@ -231,7 +231,7 @@ aio_ctx_finalize(GSource *source) AioContext *ctx = (AioContext *) source; thread_pool_free(ctx->thread_pool); - aio_set_event_notifier(ctx, &ctx->notifier, NULL); + aio_set_event_notifier(ctx, &ctx->notifier, AIO_CLIENT_UNSPECIFIED, NULL); event_notifier_cleanup(&ctx->notifier); rfifolock_destroy(&ctx->lock); qemu_mutex_destroy(&ctx->bh_lock); @@ -306,6 +306,7 @@ AioContext *aio_context_new(Error **errp) } g_source_set_can_recurse(&ctx->source, true); aio_set_event_notifier(ctx, &ctx->notifier, + AIO_CLIENT_UNSPECIFIED, (EventNotifierHandler *) event_notifier_dummy_cb); ctx->thread_pool = NULL; diff --git a/block/curl.c b/block/curl.c index 032cc8a..6925672 100644 --- a/block/curl.c +++ b/block/curl.c @@ -154,18 +154,20 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd); switch (action) { case CURL_POLL_IN: - aio_set_fd_handler(s->aio_context, fd, curl_multi_read, - NULL, state); + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + curl_multi_read, NULL, state); break; case CURL_POLL_OUT: - aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state); + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + NULL, curl_multi_do, state); break; case CURL_POLL_INOUT: - aio_set_fd_handler(s->aio_context, fd, curl_multi_read, - curl_multi_do, state); + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + curl_multi_read, curl_multi_do, state); break; case CURL_POLL_REMOVE: - aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL); + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + NULL, NULL, NULL); break; } diff --git a/block/iscsi.c b/block/iscsi.c index 5002916..0ee1295 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -291,8 +291,8 @@ iscsi_set_events(IscsiLun *iscsilun) int ev = iscsi_which_events(iscsi); if (ev != iscsilun->events) { - aio_set_fd_handler(iscsilun->aio_context, - iscsi_get_fd(iscsi), + aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsi), + AIO_CLIENT_UNSPECIFIED, (ev & POLLIN) ? iscsi_process_read : NULL, (ev & POLLOUT) ? iscsi_process_write : NULL, iscsilun); @@ -1276,9 +1276,8 @@ static void iscsi_detach_aio_context(BlockDriverState *bs) { IscsiLun *iscsilun = bs->opaque; - aio_set_fd_handler(iscsilun->aio_context, - iscsi_get_fd(iscsilun->iscsi), - NULL, NULL, NULL); + aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi), + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); iscsilun->events = 0; if (iscsilun->nop_timer) { diff --git a/block/linux-aio.c b/block/linux-aio.c index c991443..0921bde 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -287,7 +287,7 @@ void laio_detach_aio_context(void *s_, AioContext *old_context) { struct qemu_laio_state *s = s_; - aio_set_event_notifier(old_context, &s->e, NULL); + aio_set_event_notifier(old_context, &s->e, AIO_CLIENT_UNSPECIFIED, NULL); qemu_bh_delete(s->completion_bh); } @@ -296,7 +296,8 @@ void laio_attach_aio_context(void *s_, AioContext *new_context) struct qemu_laio_state *s = s_; s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); - aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb); + aio_set_event_notifier(new_context, &s->e, AIO_CLIENT_UNSPECIFIED, + qemu_laio_completion_cb); } void *laio_init(void) diff --git a/block/nbd-client.c b/block/nbd-client.c index e1bb919..36c46c5 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -124,7 +124,7 @@ static int nbd_co_send_request(BlockDriverState *bs, s->send_coroutine = qemu_coroutine_self(); aio_context = bdrv_get_aio_context(bs); - aio_set_fd_handler(aio_context, s->sock, + aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_UNSPECIFIED, nbd_reply_ready, nbd_restart_write, bs); if (qiov) { if (!s->is_unix) { @@ -144,7 +144,8 @@ static int nbd_co_send_request(BlockDriverState *bs, } else { rc = nbd_send_request(s->sock, request); } - aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, bs); + aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_UNSPECIFIED, + nbd_reply_ready, NULL, bs); s->send_coroutine = NULL; qemu_co_mutex_unlock(&s->send_mutex); return rc; @@ -348,14 +349,15 @@ int nbd_client_co_discard(BlockDriverState *bs, int64_t sector_num, void nbd_client_detach_aio_context(BlockDriverState *bs) { aio_set_fd_handler(bdrv_get_aio_context(bs), - nbd_get_client_session(bs)->sock, NULL, NULL, NULL); + nbd_get_client_session(bs)->sock, + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); } void nbd_client_attach_aio_context(BlockDriverState *bs, AioContext *new_context) { aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sock, - nbd_reply_ready, NULL, bs); + AIO_CLIENT_UNSPECIFIED, nbd_reply_ready, NULL, bs); } void nbd_client_close(BlockDriverState *bs) diff --git a/block/nfs.c b/block/nfs.c index c026ff6..a21dd6f 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -62,11 +62,10 @@ static void nfs_set_events(NFSClient *client) { int ev = nfs_which_events(client->context); if (ev != client->events) { - aio_set_fd_handler(client->aio_context, - nfs_get_fd(client->context), + aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), + AIO_CLIENT_UNSPECIFIED, (ev & POLLIN) ? nfs_process_read : NULL, - (ev & POLLOUT) ? nfs_process_write : NULL, - client); + (ev & POLLOUT) ? nfs_process_write : NULL, client); } client->events = ev; @@ -241,9 +240,8 @@ static void nfs_detach_aio_context(BlockDriverState *bs) { NFSClient *client = bs->opaque; - aio_set_fd_handler(client->aio_context, - nfs_get_fd(client->context), - NULL, NULL, NULL); + aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); client->events = 0; } @@ -262,9 +260,8 @@ static void nfs_client_close(NFSClient *client) if (client->fh) { nfs_close(client->context, client->fh); } - aio_set_fd_handler(client->aio_context, - nfs_get_fd(client->context), - NULL, NULL, NULL); + aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); nfs_destroy_context(client->context); } memset(client, 0, sizeof(NFSClient)); diff --git a/block/sheepdog.c b/block/sheepdog.c index bd7cbed..e0552b7 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -624,14 +624,16 @@ static coroutine_fn void do_co_req(void *opaque) unsigned int *rlen = srco->rlen; co = qemu_coroutine_self(); - aio_set_fd_handler(srco->aio_context, sockfd, NULL, restart_co_req, co); + aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_UNSPECIFIED, + NULL, restart_co_req, co); ret = send_co_req(sockfd, hdr, data, wlen); if (ret < 0) { goto out; } - aio_set_fd_handler(srco->aio_context, sockfd, restart_co_req, NULL, co); + aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_UNSPECIFIED, + restart_co_req, NULL, co); ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr)); if (ret != sizeof(*hdr)) { @@ -656,7 +658,8 @@ static coroutine_fn void do_co_req(void *opaque) out: /* there is at most one request for this sockfd, so it is safe to * set each handler to NULL. */ - aio_set_fd_handler(srco->aio_context, sockfd, NULL, NULL, NULL); + aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_UNSPECIFIED, + NULL, NULL, NULL); srco->ret = ret; srco->finished = true; @@ -740,7 +743,8 @@ static coroutine_fn void reconnect_to_sdog(void *opaque) BDRVSheepdogState *s = opaque; AIOReq *aio_req, *next; - aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL); + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, NULL, + NULL, NULL); close(s->fd); s->fd = -1; @@ -953,7 +957,8 @@ static int get_sheep_fd(BDRVSheepdogState *s, Error **errp) return fd; } - aio_set_fd_handler(s->aio_context, fd, co_read_response, NULL, s); + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + co_read_response, NULL, s); return fd; } @@ -1208,7 +1213,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, qemu_co_mutex_lock(&s->lock); s->co_send = qemu_coroutine_self(); - aio_set_fd_handler(s->aio_context, s->fd, + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, co_read_response, co_write_request, s); socket_set_cork(s->fd, 1); @@ -1227,7 +1232,8 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, } out: socket_set_cork(s->fd, 0); - aio_set_fd_handler(s->aio_context, s->fd, co_read_response, NULL, s); + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, + co_read_response, NULL, s); s->co_send = NULL; qemu_co_mutex_unlock(&s->lock); } @@ -1405,7 +1411,8 @@ static void sd_detach_aio_context(BlockDriverState *bs) { BDRVSheepdogState *s = bs->opaque; - aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL); + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, NULL, + NULL, NULL); } static void sd_attach_aio_context(BlockDriverState *bs, @@ -1414,7 +1421,8 @@ static void sd_attach_aio_context(BlockDriverState *bs, BDRVSheepdogState *s = bs->opaque; s->aio_context = new_context; - aio_set_fd_handler(new_context, s->fd, co_read_response, NULL, s); + aio_set_fd_handler(new_context, s->fd, AIO_CLIENT_UNSPECIFIED, + co_read_response, NULL, s); } /* TODO Convert to fine grained options */ @@ -1528,7 +1536,8 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, g_free(buf); return 0; out: - aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL); + aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); if (s->fd >= 0) { closesocket(s->fd); } @@ -1912,7 +1921,8 @@ static void sd_close(BlockDriverState *bs) error_report("%s, %s", sd_strerror(rsp->result), s->name); } - aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL); + aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); closesocket(s->fd); g_free(s->host_spec); } diff --git a/block/ssh.c b/block/ssh.c index aebb18c..71d7ffe 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -803,14 +803,15 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs) rd_handler, wr_handler); aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, - rd_handler, wr_handler, co); + AIO_CLIENT_UNSPECIFIED, rd_handler, wr_handler, co); } static coroutine_fn void clear_fd_handler(BDRVSSHState *s, BlockDriverState *bs) { DPRINTF("s->sock=%d", s->sock); - aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, NULL, NULL, NULL); + aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); } /* A non-blocking call returned EAGAIN, so yield, ensuring the diff --git a/block/win32-aio.c b/block/win32-aio.c index 64e8682..0081886 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -174,7 +174,7 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile) void win32_aio_detach_aio_context(QEMUWin32AIOState *aio, AioContext *old_context) { - aio_set_event_notifier(old_context, &aio->e, NULL); + aio_set_event_notifier(old_context, &aio->e, AIO_CLIENT_UNSPECIFIED, NULL); aio->is_aio_context_attached = false; } @@ -182,7 +182,8 @@ void win32_aio_attach_aio_context(QEMUWin32AIOState *aio, AioContext *new_context) { aio->is_aio_context_attached = true; - aio_set_event_notifier(new_context, &aio->e, win32_aio_completion_cb); + aio_set_event_notifier(new_context, &aio->e, AIO_CLIENT_UNSPECIFIED, + win32_aio_completion_cb); } QEMUWin32AIOState *win32_aio_init(void) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 3db139b..e472154 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -283,7 +283,8 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) /* Get this show started by hooking up our callbacks */ aio_context_acquire(s->ctx); - aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify); + aio_set_event_notifier(s->ctx, &s->host_notifier, AIO_CLIENT_UNSPECIFIED, + handle_notify); aio_context_release(s->ctx); return; @@ -319,7 +320,8 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) aio_context_acquire(s->ctx); /* Stop notifications for new requests from guest */ - aio_set_event_notifier(s->ctx, &s->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &s->host_notifier, AIO_CLIENT_UNSPECIFIED, + NULL); /* Drain and switch bs back to the QEMU main loop */ blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context()); diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 5575648..f7bab09 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -60,7 +60,8 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, r = g_slice_new(VirtIOSCSIVring); r->host_notifier = *virtio_queue_get_host_notifier(vq); r->guest_notifier = *virtio_queue_get_guest_notifier(vq); - aio_set_event_notifier(s->ctx, &r->host_notifier, handler); + aio_set_event_notifier(s->ctx, &r->host_notifier, AIO_CLIENT_UNSPECIFIED, + handler); r->parent = s; @@ -71,7 +72,8 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, return r; fail_vring: - aio_set_event_notifier(s->ctx, &r->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &r->host_notifier, AIO_CLIENT_UNSPECIFIED, + NULL); k->set_host_notifier(qbus->parent, n, false); g_slice_free(VirtIOSCSIVring, r); return NULL; @@ -162,14 +164,17 @@ static void virtio_scsi_clear_aio(VirtIOSCSI *s) int i; if (s->ctrl_vring) { - aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, + AIO_CLIENT_UNSPECIFIED, NULL); } if (s->event_vring) { - aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, + AIO_CLIENT_UNSPECIFIED, NULL); } if (s->cmd_vrings) { for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { - aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, + AIO_CLIENT_UNSPECIFIED, NULL); } } } @@ -290,10 +295,13 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) aio_context_acquire(s->ctx); - aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, NULL); - aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, + AIO_CLIENT_UNSPECIFIED, NULL); + aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, + AIO_CLIENT_UNSPECIFIED, NULL); for (i = 0; i < vs->conf.num_queues; i++) { - aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, NULL); + aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, + AIO_CLIENT_UNSPECIFIED, NULL); } blk_drain_all(); /* ensure there are no in-flight requests */ diff --git a/include/block/aio.h b/include/block/aio.h index 9dd32e0..bd1d44b 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -272,6 +272,9 @@ bool aio_pending(AioContext *ctx); */ bool aio_dispatch(AioContext *ctx); +#define AIO_CLIENT_UNSPECIFIED (1 << 0) +#define AIO_CLIENT_MASK_ALL -1 + /* Progress in completing AIO work to occur. This can issue new pending * aio as a result of executing I/O completion or bh callbacks. * @@ -296,6 +299,7 @@ bool aio_poll(AioContext *ctx, bool blocking); */ void aio_set_fd_handler(AioContext *ctx, int fd, + int type, IOHandler *io_read, IOHandler *io_write, void *opaque); @@ -309,6 +313,7 @@ void aio_set_fd_handler(AioContext *ctx, */ void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, + int type, EventNotifierHandler *io_read); /* Return a GSource that lets the main loop poll the file descriptors attached diff --git a/nbd.c b/nbd.c index 06b501b..64ed91b 100644 --- a/nbd.c +++ b/nbd.c @@ -1437,6 +1437,7 @@ static void nbd_set_handlers(NBDClient *client) { if (client->exp && client->exp->ctx) { aio_set_fd_handler(client->exp->ctx, client->sock, + AIO_CLIENT_UNSPECIFIED, client->can_read ? nbd_read : NULL, client->send_coroutine ? nbd_restart_write : NULL, client); @@ -1446,7 +1447,8 @@ static void nbd_set_handlers(NBDClient *client) static void nbd_unset_handlers(NBDClient *client) { if (client->exp && client->exp->ctx) { - aio_set_fd_handler(client->exp->ctx, client->sock, NULL, NULL, NULL); + aio_set_fd_handler(client->exp->ctx, client->sock, + AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); } } diff --git a/tests/test-aio.c b/tests/test-aio.c index 217e337..770119f 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -118,6 +118,12 @@ static void *test_acquire_thread(void *opaque) return NULL; } +static void set_event_notifier(AioContext *ctx, EventNotifier *notifier, + EventNotifierHandler *handler) +{ + aio_set_event_notifier(ctx, notifier, AIO_CLIENT_UNSPECIFIED, handler); +} + static void dummy_notifier_read(EventNotifier *unused) { g_assert(false); /* should never be invoked */ @@ -131,7 +137,7 @@ static void test_acquire(void) /* Dummy event notifier ensures aio_poll() will block */ event_notifier_init(¬ifier, false); - aio_set_event_notifier(ctx, ¬ifier, dummy_notifier_read); + set_event_notifier(ctx, ¬ifier, dummy_notifier_read); g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */ qemu_mutex_init(&data.start_lock); @@ -149,7 +155,7 @@ static void test_acquire(void) aio_context_release(ctx); qemu_thread_join(&thread); - aio_set_event_notifier(ctx, ¬ifier, NULL); + set_event_notifier(ctx, ¬ifier, NULL); event_notifier_cleanup(¬ifier); g_assert(data.thread_acquired); @@ -308,11 +314,11 @@ static void test_set_event_notifier(void) { EventNotifierTestData data = { .n = 0, .active = 0 }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); g_assert(!aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 0); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); g_assert(!aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 0); event_notifier_cleanup(&data.e); @@ -322,7 +328,7 @@ static void test_wait_event_notifier(void) { EventNotifierTestData data = { .n = 0, .active = 1 }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); while (aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 0); g_assert_cmpint(data.active, ==, 1); @@ -336,7 +342,7 @@ static void test_wait_event_notifier(void) g_assert_cmpint(data.n, ==, 1); g_assert_cmpint(data.active, ==, 0); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); g_assert(!aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 1); @@ -347,7 +353,7 @@ static void test_flush_event_notifier(void) { EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); while (aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 0); g_assert_cmpint(data.active, ==, 10); @@ -363,7 +369,7 @@ static void test_flush_event_notifier(void) g_assert_cmpint(data.active, ==, 0); g_assert(!aio_poll(ctx, false)); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); g_assert(!aio_poll(ctx, false)); event_notifier_cleanup(&data.e); } @@ -374,7 +380,7 @@ static void test_wait_event_notifier_noflush(void) EventNotifierTestData dummy = { .n = 0, .active = 1 }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); g_assert(!aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 0); @@ -387,7 +393,7 @@ static void test_wait_event_notifier_noflush(void) /* An active event notifier forces aio_poll to look at EventNotifiers. */ event_notifier_init(&dummy.e, false); - aio_set_event_notifier(ctx, &dummy.e, event_ready_cb); + set_event_notifier(ctx, &dummy.e, event_ready_cb); event_notifier_set(&data.e); g_assert(aio_poll(ctx, false)); @@ -407,10 +413,10 @@ static void test_wait_event_notifier_noflush(void) g_assert_cmpint(dummy.n, ==, 1); g_assert_cmpint(dummy.active, ==, 0); - aio_set_event_notifier(ctx, &dummy.e, NULL); + set_event_notifier(ctx, &dummy.e, NULL); event_notifier_cleanup(&dummy.e); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); g_assert(!aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 2); @@ -428,7 +434,7 @@ static void test_timer_schedule(void) * an fd to wait on. Fixing this breaks other tests. So create a dummy one. */ event_notifier_init(&e, false); - aio_set_event_notifier(ctx, &e, dummy_io_handler_read); + set_event_notifier(ctx, &e, dummy_io_handler_read); aio_poll(ctx, false); aio_timer_init(ctx, &data.timer, data.clock_type, @@ -467,7 +473,7 @@ static void test_timer_schedule(void) g_assert(!aio_poll(ctx, false)); g_assert_cmpint(data.n, ==, 2); - aio_set_event_notifier(ctx, &e, NULL); + set_event_notifier(ctx, &e, NULL); event_notifier_cleanup(&e); timer_del(&data.timer); @@ -638,11 +644,11 @@ static void test_source_set_event_notifier(void) { EventNotifierTestData data = { .n = 0, .active = 0 }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 0); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 0); event_notifier_cleanup(&data.e); @@ -652,7 +658,7 @@ static void test_source_wait_event_notifier(void) { EventNotifierTestData data = { .n = 0, .active = 1 }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 0); g_assert_cmpint(data.active, ==, 1); @@ -666,7 +672,7 @@ static void test_source_wait_event_notifier(void) g_assert_cmpint(data.n, ==, 1); g_assert_cmpint(data.active, ==, 0); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 1); @@ -677,7 +683,7 @@ static void test_source_flush_event_notifier(void) { EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 0); g_assert_cmpint(data.active, ==, 10); @@ -693,7 +699,7 @@ static void test_source_flush_event_notifier(void) g_assert_cmpint(data.active, ==, 0); g_assert(!g_main_context_iteration(NULL, false)); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); while (g_main_context_iteration(NULL, false)); event_notifier_cleanup(&data.e); } @@ -704,7 +710,7 @@ static void test_source_wait_event_notifier_noflush(void) EventNotifierTestData dummy = { .n = 0, .active = 1 }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, event_ready_cb); + set_event_notifier(ctx, &data.e, event_ready_cb); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 0); @@ -717,7 +723,7 @@ static void test_source_wait_event_notifier_noflush(void) /* An active event notifier forces aio_poll to look at EventNotifiers. */ event_notifier_init(&dummy.e, false); - aio_set_event_notifier(ctx, &dummy.e, event_ready_cb); + set_event_notifier(ctx, &dummy.e, event_ready_cb); event_notifier_set(&data.e); g_assert(g_main_context_iteration(NULL, false)); @@ -737,10 +743,10 @@ static void test_source_wait_event_notifier_noflush(void) g_assert_cmpint(dummy.n, ==, 1); g_assert_cmpint(dummy.active, ==, 0); - aio_set_event_notifier(ctx, &dummy.e, NULL); + set_event_notifier(ctx, &dummy.e, NULL); event_notifier_cleanup(&dummy.e); - aio_set_event_notifier(ctx, &data.e, NULL); + set_event_notifier(ctx, &data.e, NULL); while (g_main_context_iteration(NULL, false)); g_assert_cmpint(data.n, ==, 2); @@ -759,7 +765,7 @@ static void test_source_timer_schedule(void) * an fd to wait on. Fixing this breaks other tests. So create a dummy one. */ event_notifier_init(&e, false); - aio_set_event_notifier(ctx, &e, dummy_io_handler_read); + set_event_notifier(ctx, &e, dummy_io_handler_read); do {} while (g_main_context_iteration(NULL, false)); aio_timer_init(ctx, &data.timer, data.clock_type, @@ -784,7 +790,7 @@ static void test_source_timer_schedule(void) g_assert_cmpint(data.n, ==, 2); g_assert(qemu_clock_get_ns(data.clock_type) > expiry); - aio_set_event_notifier(ctx, &e, NULL); + set_event_notifier(ctx, &e, NULL); event_notifier_cleanup(&e); timer_del(&data.timer); -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier Fam Zheng @ 2015-08-27 13:50 ` Stefan Hajnoczi 0 siblings, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 13:50 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:04PM +0800, Fam Zheng wrote: > The parameter is added but not used. > > The callers are converted with following coccinelle semantic patch: > > @@ > expression E1, E2, E3, E4, E5; > @@ > ( > -aio_set_event_notifier(E1, E2, E3) > +aio_set_event_notifier(E1, E2, AIO_CLIENT_UNSPECIFIED, E3) > | > -aio_set_fd_handler(E1, E2, E3, E4, E5) > +aio_set_fd_handler(E1, E2, AIO_CLIENT_UNSPECIFIED, E3, E4, E5) > ) > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > aio-posix.c | 4 ++- > aio-win32.c | 2 ++ > async.c | 3 ++- > block/curl.c | 14 +++++----- > block/iscsi.c | 9 +++---- > block/linux-aio.c | 5 ++-- > block/nbd-client.c | 10 ++++--- > block/nfs.c | 17 +++++------- > block/sheepdog.c | 32 +++++++++++++++-------- > block/ssh.c | 5 ++-- > block/win32-aio.c | 5 ++-- > hw/block/dataplane/virtio-blk.c | 6 +++-- > hw/scsi/virtio-scsi-dataplane.c | 24 +++++++++++------ > include/block/aio.h | 5 ++++ > nbd.c | 4 ++- > tests/test-aio.c | 58 +++++++++++++++++++++++------------------ > 16 files changed, 122 insertions(+), 81 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 02/11] aio: Save type to AioHandler 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 13:50 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 03/11] block: Mark fd handlers as "protocol" Fam Zheng ` (11 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block So it can be used by aio_poll later. Signed-off-by: Fam Zheng <famz@redhat.com> --- aio-posix.c | 2 ++ aio-win32.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/aio-posix.c b/aio-posix.c index 56f2bce..d25fcfc 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -25,6 +25,7 @@ struct AioHandler IOHandler *io_write; int deleted; void *opaque; + int type; QLIST_ENTRY(AioHandler) node; }; @@ -83,6 +84,7 @@ void aio_set_fd_handler(AioContext *ctx, node->io_read = io_read; node->io_write = io_write; node->opaque = opaque; + node->type = type; node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0); node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0); diff --git a/aio-win32.c b/aio-win32.c index 90e7a4b..f5ecf57 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -28,6 +28,7 @@ struct AioHandler { GPollFD pfd; int deleted; void *opaque; + int type; QLIST_ENTRY(AioHandler) node; }; @@ -87,6 +88,7 @@ void aio_set_fd_handler(AioContext *ctx, node->opaque = opaque; node->io_read = io_read; node->io_write = io_write; + node->type = type; event = event_notifier_get_handle(&ctx->notifier); WSAEventSelect(node->pfd.fd, event, @@ -135,6 +137,7 @@ void aio_set_event_notifier(AioContext *ctx, node->e = e; node->pfd.fd = (uintptr_t)event_notifier_get_handle(e); node->pfd.events = G_IO_IN; + node->type = type; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); g_source_add_poll(&ctx->source, &node->pfd); -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 02/11] aio: Save type to AioHandler 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 02/11] aio: Save type to AioHandler Fam Zheng @ 2015-08-27 13:50 ` Stefan Hajnoczi 0 siblings, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 13:50 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:05PM +0800, Fam Zheng wrote: > So it can be used by aio_poll later. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > aio-posix.c | 2 ++ > aio-win32.c | 3 +++ > 2 files changed, 5 insertions(+) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 03/11] block: Mark fd handlers as "protocol" 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 02/11] aio: Save type to AioHandler Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 13:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 04/11] nbd: Mark fd handlers client type as "nbd server" Fam Zheng ` (10 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block The "protocol" type includes all the fd handlers and event notifiers used by block layer, especially those that should be polled in a nested event loop. Signed-off-by: Fam Zheng <famz@redhat.com> --- block/curl.c | 8 ++++---- block/iscsi.c | 4 ++-- block/linux-aio.c | 4 ++-- block/nbd-client.c | 8 ++++---- block/nfs.c | 6 +++--- block/sheepdog.c | 22 +++++++++++----------- block/ssh.c | 4 ++-- block/win32-aio.c | 4 ++-- include/block/aio.h | 1 + 9 files changed, 31 insertions(+), 30 deletions(-) diff --git a/block/curl.c b/block/curl.c index 6925672..75d237c 100644 --- a/block/curl.c +++ b/block/curl.c @@ -154,19 +154,19 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd); switch (action) { case CURL_POLL_IN: - aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_PROTOCOL, curl_multi_read, NULL, state); break; case CURL_POLL_OUT: - aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_PROTOCOL, NULL, curl_multi_do, state); break; case CURL_POLL_INOUT: - aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_PROTOCOL, curl_multi_read, curl_multi_do, state); break; case CURL_POLL_REMOVE: - aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); break; } diff --git a/block/iscsi.c b/block/iscsi.c index 0ee1295..1713625 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -292,7 +292,7 @@ iscsi_set_events(IscsiLun *iscsilun) if (ev != iscsilun->events) { aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsi), - AIO_CLIENT_UNSPECIFIED, + AIO_CLIENT_PROTOCOL, (ev & POLLIN) ? iscsi_process_read : NULL, (ev & POLLOUT) ? iscsi_process_write : NULL, iscsilun); @@ -1277,7 +1277,7 @@ static void iscsi_detach_aio_context(BlockDriverState *bs) IscsiLun *iscsilun = bs->opaque; aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi), - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); iscsilun->events = 0; if (iscsilun->nop_timer) { diff --git a/block/linux-aio.c b/block/linux-aio.c index 0921bde..1491684 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -287,7 +287,7 @@ void laio_detach_aio_context(void *s_, AioContext *old_context) { struct qemu_laio_state *s = s_; - aio_set_event_notifier(old_context, &s->e, AIO_CLIENT_UNSPECIFIED, NULL); + aio_set_event_notifier(old_context, &s->e, AIO_CLIENT_PROTOCOL, NULL); qemu_bh_delete(s->completion_bh); } @@ -296,7 +296,7 @@ void laio_attach_aio_context(void *s_, AioContext *new_context) struct qemu_laio_state *s = s_; s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); - aio_set_event_notifier(new_context, &s->e, AIO_CLIENT_UNSPECIFIED, + aio_set_event_notifier(new_context, &s->e, AIO_CLIENT_PROTOCOL, qemu_laio_completion_cb); } diff --git a/block/nbd-client.c b/block/nbd-client.c index 36c46c5..edf2199 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -124,7 +124,7 @@ static int nbd_co_send_request(BlockDriverState *bs, s->send_coroutine = qemu_coroutine_self(); aio_context = bdrv_get_aio_context(bs); - aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_PROTOCOL, nbd_reply_ready, nbd_restart_write, bs); if (qiov) { if (!s->is_unix) { @@ -144,7 +144,7 @@ static int nbd_co_send_request(BlockDriverState *bs, } else { rc = nbd_send_request(s->sock, request); } - aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_PROTOCOL, nbd_reply_ready, NULL, bs); s->send_coroutine = NULL; qemu_co_mutex_unlock(&s->send_mutex); @@ -350,14 +350,14 @@ void nbd_client_detach_aio_context(BlockDriverState *bs) { aio_set_fd_handler(bdrv_get_aio_context(bs), nbd_get_client_session(bs)->sock, - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); } void nbd_client_attach_aio_context(BlockDriverState *bs, AioContext *new_context) { aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sock, - AIO_CLIENT_UNSPECIFIED, nbd_reply_ready, NULL, bs); + AIO_CLIENT_PROTOCOL, nbd_reply_ready, NULL, bs); } void nbd_client_close(BlockDriverState *bs) diff --git a/block/nfs.c b/block/nfs.c index a21dd6f..4d12067 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -63,7 +63,7 @@ static void nfs_set_events(NFSClient *client) int ev = nfs_which_events(client->context); if (ev != client->events) { aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - AIO_CLIENT_UNSPECIFIED, + AIO_CLIENT_PROTOCOL, (ev & POLLIN) ? nfs_process_read : NULL, (ev & POLLOUT) ? nfs_process_write : NULL, client); @@ -241,7 +241,7 @@ static void nfs_detach_aio_context(BlockDriverState *bs) NFSClient *client = bs->opaque; aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); client->events = 0; } @@ -261,7 +261,7 @@ static void nfs_client_close(NFSClient *client) nfs_close(client->context, client->fh); } aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); nfs_destroy_context(client->context); } memset(client, 0, sizeof(NFSClient)); diff --git a/block/sheepdog.c b/block/sheepdog.c index e0552b7..de9f8be 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -624,7 +624,7 @@ static coroutine_fn void do_co_req(void *opaque) unsigned int *rlen = srco->rlen; co = qemu_coroutine_self(); - aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_PROTOCOL, NULL, restart_co_req, co); ret = send_co_req(sockfd, hdr, data, wlen); @@ -632,7 +632,7 @@ static coroutine_fn void do_co_req(void *opaque) goto out; } - aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_PROTOCOL, restart_co_req, NULL, co); ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr)); @@ -658,7 +658,7 @@ static coroutine_fn void do_co_req(void *opaque) out: /* there is at most one request for this sockfd, so it is safe to * set each handler to NULL. */ - aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(srco->aio_context, sockfd, AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); srco->ret = ret; @@ -743,7 +743,7 @@ static coroutine_fn void reconnect_to_sdog(void *opaque) BDRVSheepdogState *s = opaque; AIOReq *aio_req, *next; - aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, NULL, + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); close(s->fd); s->fd = -1; @@ -957,7 +957,7 @@ static int get_sheep_fd(BDRVSheepdogState *s, Error **errp) return fd; } - aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, fd, AIO_CLIENT_PROTOCOL, co_read_response, NULL, s); return fd; } @@ -1213,7 +1213,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, qemu_co_mutex_lock(&s->lock); s->co_send = qemu_coroutine_self(); - aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_PROTOCOL, co_read_response, co_write_request, s); socket_set_cork(s->fd, 1); @@ -1232,7 +1232,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, } out: socket_set_cork(s->fd, 0); - aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_PROTOCOL, co_read_response, NULL, s); s->co_send = NULL; qemu_co_mutex_unlock(&s->lock); @@ -1411,7 +1411,7 @@ static void sd_detach_aio_context(BlockDriverState *bs) { BDRVSheepdogState *s = bs->opaque; - aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_UNSPECIFIED, NULL, + aio_set_fd_handler(s->aio_context, s->fd, AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); } @@ -1421,7 +1421,7 @@ static void sd_attach_aio_context(BlockDriverState *bs, BDRVSheepdogState *s = bs->opaque; s->aio_context = new_context; - aio_set_fd_handler(new_context, s->fd, AIO_CLIENT_UNSPECIFIED, + aio_set_fd_handler(new_context, s->fd, AIO_CLIENT_PROTOCOL, co_read_response, NULL, s); } @@ -1537,7 +1537,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, return 0; out: aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); if (s->fd >= 0) { closesocket(s->fd); } @@ -1922,7 +1922,7 @@ static void sd_close(BlockDriverState *bs) } aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); closesocket(s->fd); g_free(s->host_spec); } diff --git a/block/ssh.c b/block/ssh.c index 71d7ffe..3e721d2 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -803,7 +803,7 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs) rd_handler, wr_handler); aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, - AIO_CLIENT_UNSPECIFIED, rd_handler, wr_handler, co); + AIO_CLIENT_PROTOCOL, rd_handler, wr_handler, co); } static coroutine_fn void clear_fd_handler(BDRVSSHState *s, @@ -811,7 +811,7 @@ static coroutine_fn void clear_fd_handler(BDRVSSHState *s, { DPRINTF("s->sock=%d", s->sock); aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_PROTOCOL, NULL, NULL, NULL); } /* A non-blocking call returned EAGAIN, so yield, ensuring the diff --git a/block/win32-aio.c b/block/win32-aio.c index 0081886..57b1916 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -174,7 +174,7 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile) void win32_aio_detach_aio_context(QEMUWin32AIOState *aio, AioContext *old_context) { - aio_set_event_notifier(old_context, &aio->e, AIO_CLIENT_UNSPECIFIED, NULL); + aio_set_event_notifier(old_context, &aio->e, AIO_CLIENT_PROTOCOL, NULL); aio->is_aio_context_attached = false; } @@ -182,7 +182,7 @@ void win32_aio_attach_aio_context(QEMUWin32AIOState *aio, AioContext *new_context) { aio->is_aio_context_attached = true; - aio_set_event_notifier(new_context, &aio->e, AIO_CLIENT_UNSPECIFIED, + aio_set_event_notifier(new_context, &aio->e, AIO_CLIENT_PROTOCOL, win32_aio_completion_cb); } diff --git a/include/block/aio.h b/include/block/aio.h index bd1d44b..d02ddfa 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -273,6 +273,7 @@ bool aio_pending(AioContext *ctx); bool aio_dispatch(AioContext *ctx); #define AIO_CLIENT_UNSPECIFIED (1 << 0) +#define AIO_CLIENT_PROTOCOL (1 << 1) #define AIO_CLIENT_MASK_ALL -1 /* Progress in completing AIO work to occur. This can issue new pending -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 03/11] block: Mark fd handlers as "protocol" 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 03/11] block: Mark fd handlers as "protocol" Fam Zheng @ 2015-08-27 13:53 ` Stefan Hajnoczi 2015-09-07 4:43 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 13:53 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:06PM +0800, Fam Zheng wrote: > diff --git a/include/block/aio.h b/include/block/aio.h > index bd1d44b..d02ddfa 100644 > --- a/include/block/aio.h > +++ b/include/block/aio.h > @@ -273,6 +273,7 @@ bool aio_pending(AioContext *ctx); > bool aio_dispatch(AioContext *ctx); > > #define AIO_CLIENT_UNSPECIFIED (1 << 0) > +#define AIO_CLIENT_PROTOCOL (1 << 1) The semantics need to be documented here, not just in the commit description. AIO_CLIENT_BLOCK_DRIVER or AIO_CLIENT_BLOCK_PROTOCOL seems like a clearer name to me since "protocol" just by itself could mean many things. ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 03/11] block: Mark fd handlers as "protocol" 2015-08-27 13:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi @ 2015-09-07 4:43 ` Fam Zheng 0 siblings, 0 replies; 54+ messages in thread From: Fam Zheng @ 2015-09-07 4:43 UTC (permalink / raw) To: Stefan Hajnoczi; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Thu, 08/27 14:53, Stefan Hajnoczi wrote: > On Wed, Jul 29, 2015 at 12:42:06PM +0800, Fam Zheng wrote: > > diff --git a/include/block/aio.h b/include/block/aio.h > > index bd1d44b..d02ddfa 100644 > > --- a/include/block/aio.h > > +++ b/include/block/aio.h > > @@ -273,6 +273,7 @@ bool aio_pending(AioContext *ctx); > > bool aio_dispatch(AioContext *ctx); > > > > #define AIO_CLIENT_UNSPECIFIED (1 << 0) > > +#define AIO_CLIENT_PROTOCOL (1 << 1) > > The semantics need to be documented here, not just in the commit > description. > > AIO_CLIENT_BLOCK_DRIVER or AIO_CLIENT_BLOCK_PROTOCOL seems like a > clearer name to me since "protocol" just by itself could mean many > things. OK, renaming to AIO_CLIENT_BLOCK_DRIVER. Thanks, Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 04/11] nbd: Mark fd handlers client type as "nbd server" 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (2 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 03/11] block: Mark fd handlers as "protocol" Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 14:02 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 05/11] aio: Mark ctx->notifier's client type as "context" Fam Zheng ` (9 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block So we could distinguish it from "protocol" to avoid handling in nested aio polls. Signed-off-by: Fam Zheng <famz@redhat.com> --- include/block/aio.h | 1 + nbd.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/block/aio.h b/include/block/aio.h index d02ddfa..8b15105 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -274,6 +274,7 @@ bool aio_dispatch(AioContext *ctx); #define AIO_CLIENT_UNSPECIFIED (1 << 0) #define AIO_CLIENT_PROTOCOL (1 << 1) +#define AIO_CLIENT_NBD_SERVER (1 << 2) #define AIO_CLIENT_MASK_ALL -1 /* Progress in completing AIO work to occur. This can issue new pending diff --git a/nbd.c b/nbd.c index 64ed91b..7b38334 100644 --- a/nbd.c +++ b/nbd.c @@ -1437,7 +1437,7 @@ static void nbd_set_handlers(NBDClient *client) { if (client->exp && client->exp->ctx) { aio_set_fd_handler(client->exp->ctx, client->sock, - AIO_CLIENT_UNSPECIFIED, + AIO_CLIENT_NBD_SERVER, client->can_read ? nbd_read : NULL, client->send_coroutine ? nbd_restart_write : NULL, client); @@ -1448,7 +1448,7 @@ static void nbd_unset_handlers(NBDClient *client) { if (client->exp && client->exp->ctx) { aio_set_fd_handler(client->exp->ctx, client->sock, - AIO_CLIENT_UNSPECIFIED, NULL, NULL, NULL); + AIO_CLIENT_NBD_SERVER, NULL, NULL, NULL); } } -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 04/11] nbd: Mark fd handlers client type as "nbd server" 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 04/11] nbd: Mark fd handlers client type as "nbd server" Fam Zheng @ 2015-08-27 14:02 ` Stefan Hajnoczi 0 siblings, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 14:02 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:07PM +0800, Fam Zheng wrote: > So we could distinguish it from "protocol" to avoid handling in nested aio > polls. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > include/block/aio.h | 1 + > nbd.c | 4 ++-- > 2 files changed, 3 insertions(+), 2 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 05/11] aio: Mark ctx->notifier's client type as "context" 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (3 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 04/11] nbd: Mark fd handlers client type as "nbd server" Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 17:12 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 06/11] dataplane: Mark host notifiers' client type as "dataplane" Fam Zheng ` (8 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block It is important to include this for any blocking poll, on the other hand it is also OK to exclude it otherwise. Signed-off-by: Fam Zheng <famz@redhat.com> --- async.c | 4 ++-- include/block/aio.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/async.c b/async.c index 43f9425..0bea602 100644 --- a/async.c +++ b/async.c @@ -231,7 +231,7 @@ aio_ctx_finalize(GSource *source) AioContext *ctx = (AioContext *) source; thread_pool_free(ctx->thread_pool); - aio_set_event_notifier(ctx, &ctx->notifier, AIO_CLIENT_UNSPECIFIED, NULL); + aio_set_event_notifier(ctx, &ctx->notifier, AIO_CLIENT_CONTEXT, NULL); event_notifier_cleanup(&ctx->notifier); rfifolock_destroy(&ctx->lock); qemu_mutex_destroy(&ctx->bh_lock); @@ -306,7 +306,7 @@ AioContext *aio_context_new(Error **errp) } g_source_set_can_recurse(&ctx->source, true); aio_set_event_notifier(ctx, &ctx->notifier, - AIO_CLIENT_UNSPECIFIED, + AIO_CLIENT_CONTEXT, (EventNotifierHandler *) event_notifier_dummy_cb); ctx->thread_pool = NULL; diff --git a/include/block/aio.h b/include/block/aio.h index 8b15105..b0b2345 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -275,6 +275,7 @@ bool aio_dispatch(AioContext *ctx); #define AIO_CLIENT_UNSPECIFIED (1 << 0) #define AIO_CLIENT_PROTOCOL (1 << 1) #define AIO_CLIENT_NBD_SERVER (1 << 2) +#define AIO_CLIENT_CONTEXT (1 << 3) #define AIO_CLIENT_MASK_ALL -1 /* Progress in completing AIO work to occur. This can issue new pending -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 05/11] aio: Mark ctx->notifier's client type as "context" 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 05/11] aio: Mark ctx->notifier's client type as "context" Fam Zheng @ 2015-08-27 17:12 ` Stefan Hajnoczi 0 siblings, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 17:12 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:08PM +0800, Fam Zheng wrote: > It is important to include this for any blocking poll, on the other hand it is > also OK to exclude it otherwise. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > async.c | 4 ++-- > include/block/aio.h | 1 + > 2 files changed, 3 insertions(+), 2 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 06/11] dataplane: Mark host notifiers' client type as "dataplane" 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (4 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 05/11] aio: Mark ctx->notifier's client type as "context" Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 17:14 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients Fam Zheng ` (7 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block Signed-off-by: Fam Zheng <famz@redhat.com> --- hw/block/dataplane/virtio-blk.c | 4 ++-- hw/scsi/virtio-scsi-dataplane.c | 16 ++++++++-------- include/block/aio.h | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index e472154..5419f1c 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -283,7 +283,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) /* Get this show started by hooking up our callbacks */ aio_context_acquire(s->ctx); - aio_set_event_notifier(s->ctx, &s->host_notifier, AIO_CLIENT_UNSPECIFIED, + aio_set_event_notifier(s->ctx, &s->host_notifier, AIO_CLIENT_DATAPLANE, handle_notify); aio_context_release(s->ctx); return; @@ -320,7 +320,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) aio_context_acquire(s->ctx); /* Stop notifications for new requests from guest */ - aio_set_event_notifier(s->ctx, &s->host_notifier, AIO_CLIENT_UNSPECIFIED, + aio_set_event_notifier(s->ctx, &s->host_notifier, AIO_CLIENT_DATAPLANE, NULL); /* Drain and switch bs back to the QEMU main loop */ diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index f7bab09..55c2524 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -60,7 +60,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, r = g_slice_new(VirtIOSCSIVring); r->host_notifier = *virtio_queue_get_host_notifier(vq); r->guest_notifier = *virtio_queue_get_guest_notifier(vq); - aio_set_event_notifier(s->ctx, &r->host_notifier, AIO_CLIENT_UNSPECIFIED, + aio_set_event_notifier(s->ctx, &r->host_notifier, AIO_CLIENT_DATAPLANE, handler); r->parent = s; @@ -72,7 +72,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, return r; fail_vring: - aio_set_event_notifier(s->ctx, &r->host_notifier, AIO_CLIENT_UNSPECIFIED, + aio_set_event_notifier(s->ctx, &r->host_notifier, AIO_CLIENT_DATAPLANE, NULL); k->set_host_notifier(qbus->parent, n, false); g_slice_free(VirtIOSCSIVring, r); @@ -165,16 +165,16 @@ static void virtio_scsi_clear_aio(VirtIOSCSI *s) if (s->ctrl_vring) { aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, - AIO_CLIENT_UNSPECIFIED, NULL); + AIO_CLIENT_DATAPLANE, NULL); } if (s->event_vring) { aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, - AIO_CLIENT_UNSPECIFIED, NULL); + AIO_CLIENT_DATAPLANE, NULL); } if (s->cmd_vrings) { for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, - AIO_CLIENT_UNSPECIFIED, NULL); + AIO_CLIENT_DATAPLANE, NULL); } } } @@ -296,12 +296,12 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) aio_context_acquire(s->ctx); aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, - AIO_CLIENT_UNSPECIFIED, NULL); + AIO_CLIENT_DATAPLANE, NULL); aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, - AIO_CLIENT_UNSPECIFIED, NULL); + AIO_CLIENT_DATAPLANE, NULL); for (i = 0; i < vs->conf.num_queues; i++) { aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, - AIO_CLIENT_UNSPECIFIED, NULL); + AIO_CLIENT_DATAPLANE, NULL); } blk_drain_all(); /* ensure there are no in-flight requests */ diff --git a/include/block/aio.h b/include/block/aio.h index b0b2345..9541bdd 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -276,6 +276,7 @@ bool aio_dispatch(AioContext *ctx); #define AIO_CLIENT_PROTOCOL (1 << 1) #define AIO_CLIENT_NBD_SERVER (1 << 2) #define AIO_CLIENT_CONTEXT (1 << 3) +#define AIO_CLIENT_DATAPLANE (1 << 4) #define AIO_CLIENT_MASK_ALL -1 /* Progress in completing AIO work to occur. This can issue new pending -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 06/11] dataplane: Mark host notifiers' client type as "dataplane" 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 06/11] dataplane: Mark host notifiers' client type as "dataplane" Fam Zheng @ 2015-08-27 17:14 ` Stefan Hajnoczi 0 siblings, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 17:14 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:09PM +0800, Fam Zheng wrote: > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > hw/block/dataplane/virtio-blk.c | 4 ++-- > hw/scsi/virtio-scsi-dataplane.c | 16 ++++++++-------- > include/block/aio.h | 1 + > 3 files changed, 11 insertions(+), 10 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (5 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 06/11] dataplane: Mark host notifiers' client type as "dataplane" Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 17:23 ` Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 08/11] aio-win32: Implement " Fam Zheng ` (6 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block Signed-off-by: Fam Zheng <famz@redhat.com> --- aio-posix.c | 17 ++++++++++++++++- include/block/aio.h | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/aio-posix.c b/aio-posix.c index d25fcfc..840b769 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -26,6 +26,7 @@ struct AioHandler int deleted; void *opaque; int type; + int disable_cnt; QLIST_ENTRY(AioHandler) node; }; @@ -261,7 +262,7 @@ bool aio_poll(AioContext *ctx, bool blocking) /* fill pollfds */ QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (!node->deleted && node->pfd.events) { + if (!node->deleted && node->pfd.events && !node->disable_cnt) { add_pollfd(node); } } @@ -301,3 +302,17 @@ bool aio_poll(AioContext *ctx, bool blocking) return progress; } + +void aio_disable_enable_clients(AioContext *ctx, int clients_mask, + bool is_disable) +{ + AioHandler *node; + aio_context_acquire(ctx); + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + if (!node->deleted && node->type & clients_mask) { + node->disable_cnt += is_disable ? 1 : -1; + } + } + aio_context_release(ctx); +} diff --git a/include/block/aio.h b/include/block/aio.h index 9541bdd..fb70cc5 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -379,4 +379,28 @@ static inline void aio_timer_init(AioContext *ctx, */ int64_t aio_compute_timeout(AioContext *ctx); +void aio_disable_enable_clients(AioContext *ctx, int clients_mask, + bool is_disable); +/** + * aio_disable_clients: + * @ctx: the aio context + * + * Disable the furthur processing by aio_poll(ctx) of clients. + */ +static inline void aio_disable_clients(AioContext *ctx, int clients_mask) +{ + aio_disable_enable_clients(ctx, clients_mask, true); +} + +/** + * aio_enable_clients: + * @ctx: the aio context + * + * Enable the processing of the clients. + */ +static inline void aio_enable_clients(AioContext *ctx, int clients_mask) +{ + aio_disable_enable_clients(ctx, clients_mask, false); +} + #endif -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients Fam Zheng @ 2015-08-27 17:23 ` Stefan Hajnoczi 2015-09-07 5:26 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 17:23 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:10PM +0800, Fam Zheng wrote: > +void aio_disable_enable_clients(AioContext *ctx, int clients_mask, > + bool is_disable) > +{ > + AioHandler *node; > + aio_context_acquire(ctx); > + > + QLIST_FOREACH(node, &ctx->aio_handlers, node) { > + if (!node->deleted && node->type & clients_mask) { > + node->disable_cnt += is_disable ? 1 : -1; > + } > + } > + aio_context_release(ctx); > +} If someone adds an fd of a disabled type *after* the call to aio_disable_clients() then it won't be disabled. Another approach is to keep an array of counters per AioContext and check the counters during aio_poll() when deciding which fds to monitor. Also, this function acquires/releases AioContext so it's worth mentioning in the doc comments that this function is thread-safe. ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients 2015-08-27 17:23 ` Stefan Hajnoczi @ 2015-09-07 5:26 ` Fam Zheng 0 siblings, 0 replies; 54+ messages in thread From: Fam Zheng @ 2015-09-07 5:26 UTC (permalink / raw) To: Stefan Hajnoczi; +Cc: kwolf, pbonzini, stefanha, qemu-devel, qemu-block On Thu, 08/27 18:23, Stefan Hajnoczi wrote: > On Wed, Jul 29, 2015 at 12:42:10PM +0800, Fam Zheng wrote: > > +void aio_disable_enable_clients(AioContext *ctx, int clients_mask, > > + bool is_disable) > > +{ > > + AioHandler *node; > > + aio_context_acquire(ctx); > > + > > + QLIST_FOREACH(node, &ctx->aio_handlers, node) { > > + if (!node->deleted && node->type & clients_mask) { > > + node->disable_cnt += is_disable ? 1 : -1; > > + } > > + } > > + aio_context_release(ctx); > > +} > > If someone adds an fd of a disabled type *after* the call to > aio_disable_clients() then it won't be disabled. > > Another approach is to keep an array of counters per AioContext and > check the counters during aio_poll() when deciding which fds to monitor. Good idea, I'll change that way. > > Also, this function acquires/releases AioContext so it's worth > mentioning in the doc comments that this function is thread-safe. > OK. Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 08/11] aio-win32: Implement aio_{disable, enable}_clients 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (6 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 09/11] block: Introduce bdrv_aio_poll Fam Zheng ` (5 subsequent siblings) 13 siblings, 0 replies; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block Signed-off-by: Fam Zheng <famz@redhat.com> --- aio-win32.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/aio-win32.c b/aio-win32.c index f5ecf57..1f6a3f0 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -28,6 +28,7 @@ struct AioHandler { GPollFD pfd; int deleted; void *opaque; + int disable_cnt; int type; QLIST_ENTRY(AioHandler) node; }; @@ -309,7 +310,7 @@ bool aio_poll(AioContext *ctx, bool blocking) /* fill fd sets */ count = 0; QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (!node->deleted && node->io_notify) { + if (!node->deleted && node->io_notify && !node->disable_cnt) { events[count++] = event_notifier_get_handle(node->e); } } @@ -368,3 +369,17 @@ bool aio_poll(AioContext *ctx, bool blocking) aio_context_release(ctx); return progress; } + +void aio_disable_enable_clients(AioContext *ctx, int clients_mask, + bool is_disable) +{ + AioHandler *node; + aio_context_acquire(ctx); + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + if (!node->deleted && node->type & clients_mask) { + node->disable_cnt += is_disable ? 1 : -1; + } + } + aio_context_release(ctx); +} -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 09/11] block: Introduce bdrv_aio_poll 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (7 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 08/11] aio-win32: Implement " Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-27 17:25 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-08-28 11:50 ` Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 10/11] block: Replace nested aio_poll with bdrv_aio_poll Fam Zheng ` (4 subsequent siblings) 13 siblings, 2 replies; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block This call is introduced simply as a wrapper of aio_poll, but it makes it is easy to change the polled client types. Signed-off-by: Fam Zheng <famz@redhat.com> --- block/io.c | 8 ++++++++ include/block/aio.h | 2 +- include/block/block.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/block/io.c b/block/io.c index d4bc83b..aca5dff 100644 --- a/block/io.c +++ b/block/io.c @@ -2608,3 +2608,11 @@ void bdrv_flush_io_queue(BlockDriverState *bs) } bdrv_start_throttled_reqs(bs); } + +bool bdrv_aio_poll(AioContext *ctx, bool blocking) +{ + bool ret; + + ret = aio_poll(ctx, blocking); + return ret; +} diff --git a/include/block/aio.h b/include/block/aio.h index fb70cc5..53fc400 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -385,7 +385,7 @@ void aio_disable_enable_clients(AioContext *ctx, int clients_mask, * aio_disable_clients: * @ctx: the aio context * - * Disable the furthur processing by aio_poll(ctx) of clients. + * Disable the processing of clients by further aio_poll(ctx). */ static inline void aio_disable_clients(AioContext *ctx, int clients_mask) { diff --git a/include/block/block.h b/include/block/block.h index 37916f7..be99e6d 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -616,4 +616,6 @@ void bdrv_flush_io_queue(BlockDriverState *bs); BlockAcctStats *bdrv_get_stats(BlockDriverState *bs); +bool bdrv_aio_poll(AioContext *ctx, bool blocking); + #endif -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 09/11] block: Introduce bdrv_aio_poll 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 09/11] block: Introduce bdrv_aio_poll Fam Zheng @ 2015-08-27 17:25 ` Stefan Hajnoczi 2015-08-28 11:50 ` Stefan Hajnoczi 1 sibling, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-27 17:25 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:12PM +0800, Fam Zheng wrote: > This call is introduced simply as a wrapper of aio_poll, but it makes it > is easy to change the polled client types. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > block/io.c | 8 ++++++++ > include/block/aio.h | 2 +- > include/block/block.h | 2 ++ > 3 files changed, 11 insertions(+), 1 deletion(-) > > diff --git a/block/io.c b/block/io.c > index d4bc83b..aca5dff 100644 > --- a/block/io.c > +++ b/block/io.c > @@ -2608,3 +2608,11 @@ void bdrv_flush_io_queue(BlockDriverState *bs) > } > bdrv_start_throttled_reqs(bs); > } > + > +bool bdrv_aio_poll(AioContext *ctx, bool blocking) > +{ > + bool ret; > + > + ret = aio_poll(ctx, blocking); > + return ret; > +} > diff --git a/include/block/aio.h b/include/block/aio.h > index fb70cc5..53fc400 100644 > --- a/include/block/aio.h > +++ b/include/block/aio.h > @@ -385,7 +385,7 @@ void aio_disable_enable_clients(AioContext *ctx, int clients_mask, > * aio_disable_clients: > * @ctx: the aio context > * > - * Disable the furthur processing by aio_poll(ctx) of clients. > + * Disable the processing of clients by further aio_poll(ctx). Should this be squashed into an earlier patch? ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 09/11] block: Introduce bdrv_aio_poll 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 09/11] block: Introduce bdrv_aio_poll Fam Zheng 2015-08-27 17:25 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi @ 2015-08-28 11:50 ` Stefan Hajnoczi 1 sibling, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-28 11:50 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:12PM +0800, Fam Zheng wrote: > +bool bdrv_aio_poll(AioContext *ctx, bool blocking) > +{ > + bool ret; > + > + ret = aio_poll(ctx, blocking); > + return ret; > +} This function would fit into bdrv_*() APIs better if the first argument was BlockDriverState *bs instead of an AioContext. ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 10/11] block: Replace nested aio_poll with bdrv_aio_poll 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (8 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 09/11] block: Introduce bdrv_aio_poll Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-08-28 11:50 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll Fam Zheng ` (3 subsequent siblings) 13 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block Just a manual search and replace. No semantic change here. Signed-off-by: Fam Zheng <famz@redhat.com> --- block.c | 2 +- block/curl.c | 2 +- block/io.c | 18 +++++++++--------- block/nfs.c | 2 +- block/qed-table.c | 8 ++++---- blockjob.c | 2 +- qemu-img.c | 2 +- qemu-io-cmds.c | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/block.c b/block.c index d088ee0..564c43b 100644 --- a/block.c +++ b/block.c @@ -371,7 +371,7 @@ int bdrv_create(BlockDriver *drv, const char* filename, co = qemu_coroutine_create(bdrv_create_co_entry); qemu_coroutine_enter(co, &cco); while (cco.ret == NOT_DONE) { - aio_poll(qemu_get_aio_context(), true); + bdrv_aio_poll(qemu_get_aio_context(), true); } } diff --git a/block/curl.c b/block/curl.c index 75d237c..2223091 100644 --- a/block/curl.c +++ b/block/curl.c @@ -392,7 +392,7 @@ static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s) break; } if (!state) { - aio_poll(bdrv_get_aio_context(bs), true); + bdrv_aio_poll(bdrv_get_aio_context(bs), true); } } while(!state); diff --git a/block/io.c b/block/io.c index aca5dff..3d255e0 100644 --- a/block/io.c +++ b/block/io.c @@ -251,7 +251,7 @@ void bdrv_drain(BlockDriverState *bs) /* Keep iterating */ bdrv_flush_io_queue(bs); busy = bdrv_requests_pending(bs); - busy |= aio_poll(bdrv_get_aio_context(bs), busy); + busy |= bdrv_aio_poll(bdrv_get_aio_context(bs), busy); } } @@ -301,11 +301,11 @@ void bdrv_drain_all(void) bdrv_flush_io_queue(bs); if (bdrv_requests_pending(bs)) { busy = true; - aio_poll(aio_context, busy); + bdrv_aio_poll(aio_context, busy); } } } - busy |= aio_poll(aio_context, false); + busy |= bdrv_aio_poll(aio_context, false); aio_context_release(aio_context); } } @@ -559,7 +559,7 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset, co = qemu_coroutine_create(bdrv_rw_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { - aio_poll(aio_context, true); + bdrv_aio_poll(aio_context, true); } } return rwco.ret; @@ -1594,7 +1594,7 @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs, co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry); qemu_coroutine_enter(co, &data); while (!data.done) { - aio_poll(aio_context, true); + bdrv_aio_poll(aio_context, true); } } return data.ret; @@ -1962,9 +1962,9 @@ void bdrv_aio_cancel(BlockAIOCB *acb) bdrv_aio_cancel_async(acb); while (acb->refcnt > 1) { if (acb->aiocb_info->get_aio_context) { - aio_poll(acb->aiocb_info->get_aio_context(acb), true); + bdrv_aio_poll(acb->aiocb_info->get_aio_context(acb), true); } else if (acb->bs) { - aio_poll(bdrv_get_aio_context(acb->bs), true); + bdrv_aio_poll(bdrv_get_aio_context(acb->bs), true); } else { abort(); } @@ -2376,7 +2376,7 @@ int bdrv_flush(BlockDriverState *bs) co = qemu_coroutine_create(bdrv_flush_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { - aio_poll(aio_context, true); + bdrv_aio_poll(aio_context, true); } } @@ -2489,7 +2489,7 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) co = qemu_coroutine_create(bdrv_discard_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { - aio_poll(aio_context, true); + bdrv_aio_poll(aio_context, true); } } diff --git a/block/nfs.c b/block/nfs.c index 4d12067..6740661 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -469,7 +469,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) while (!task.complete) { nfs_set_events(client); - aio_poll(client->aio_context, true); + bdrv_aio_poll(client->aio_context, true); } return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize); diff --git a/block/qed-table.c b/block/qed-table.c index 513aa87..6421ce7 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -173,7 +173,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s) qed_read_table(s, s->header.l1_table_offset, s->l1_table, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { - aio_poll(bdrv_get_aio_context(s->bs), true); + bdrv_aio_poll(bdrv_get_aio_context(s->bs), true); } return ret; @@ -194,7 +194,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, qed_write_l1_table(s, index, n, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { - aio_poll(bdrv_get_aio_context(s->bs), true); + bdrv_aio_poll(bdrv_get_aio_context(s->bs), true); } return ret; @@ -267,7 +267,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset qed_read_l2_table(s, request, offset, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { - aio_poll(bdrv_get_aio_context(s->bs), true); + bdrv_aio_poll(bdrv_get_aio_context(s->bs), true); } return ret; @@ -289,7 +289,7 @@ int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { - aio_poll(bdrv_get_aio_context(s->bs), true); + bdrv_aio_poll(bdrv_get_aio_context(s->bs), true); } return ret; diff --git a/blockjob.c b/blockjob.c index 62bb906..4e52652 100644 --- a/blockjob.c +++ b/blockjob.c @@ -210,7 +210,7 @@ static int block_job_finish_sync(BlockJob *job, return -EBUSY; } while (data.ret == -EINPROGRESS) { - aio_poll(bdrv_get_aio_context(bs), true); + bdrv_aio_poll(bdrv_get_aio_context(bs), true); } return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; } diff --git a/qemu-img.c b/qemu-img.c index 75f4ee4..5c0f73b 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -654,7 +654,7 @@ static void run_block_job(BlockJob *job, Error **errp) AioContext *aio_context = bdrv_get_aio_context(job->bs); do { - aio_poll(aio_context, true); + bdrv_aio_poll(aio_context, true); qemu_progress_print((float)job->offset / job->len * 100.f, 0); } while (!job->ready); diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 53477e1..b7c0e64 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -478,7 +478,7 @@ static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int count, co = qemu_coroutine_create(co_write_zeroes_entry); qemu_coroutine_enter(co, &data); while (!data.done) { - aio_poll(blk_get_aio_context(blk), true); + bdrv_aio_poll(blk_get_aio_context(blk), true); } if (data.ret < 0) { return data.ret; @@ -2046,7 +2046,7 @@ static const cmdinfo_t resume_cmd = { static int wait_break_f(BlockBackend *blk, int argc, char **argv) { while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) { - aio_poll(blk_get_aio_context(blk), true); + bdrv_aio_poll(blk_get_aio_context(blk), true); } return 0; -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 10/11] block: Replace nested aio_poll with bdrv_aio_poll 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 10/11] block: Replace nested aio_poll with bdrv_aio_poll Fam Zheng @ 2015-08-28 11:50 ` Stefan Hajnoczi 0 siblings, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-28 11:50 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:13PM +0800, Fam Zheng wrote: > Just a manual search and replace. No semantic change here. > > Signed-off-by: Fam Zheng <famz@redhat.com> > --- > block.c | 2 +- > block/curl.c | 2 +- > block/io.c | 18 +++++++++--------- > block/nfs.c | 2 +- > block/qed-table.c | 8 ++++---- > blockjob.c | 2 +- > qemu-img.c | 2 +- > qemu-io-cmds.c | 4 ++-- > 8 files changed, 20 insertions(+), 20 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (9 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 10/11] block: Replace nested aio_poll with bdrv_aio_poll Fam Zheng @ 2015-07-29 4:42 ` Fam Zheng 2015-07-29 7:36 ` Paolo Bonzini 2015-07-29 7:37 ` Paolo Bonzini 2015-07-29 7:38 ` [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Paolo Bonzini ` (2 subsequent siblings) 13 siblings, 2 replies; 54+ messages in thread From: Fam Zheng @ 2015-07-29 4:42 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, pbonzini, stefanha, qemu-block So that external events are not processed in nested event loops. Signed-off-by: Fam Zheng <famz@redhat.com> --- block/io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/io.c b/block/io.c index 3d255e0..84047fe 100644 --- a/block/io.c +++ b/block/io.c @@ -2613,6 +2613,8 @@ bool bdrv_aio_poll(AioContext *ctx, bool blocking) { bool ret; + aio_disable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); ret = aio_poll(ctx, blocking); + aio_enable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); return ret; } -- 2.4.3 ^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll Fam Zheng @ 2015-07-29 7:36 ` Paolo Bonzini 2015-07-29 7:37 ` Paolo Bonzini 1 sibling, 0 replies; 54+ messages in thread From: Paolo Bonzini @ 2015-07-29 7:36 UTC (permalink / raw) To: Fam Zheng, qemu-devel; +Cc: kwolf, qemu-block, stefanha On 29/07/2015 06:42, Fam Zheng wrote: > @@ -2613,6 +2613,8 @@ bool bdrv_aio_poll(AioContext *ctx, bool blocking) > { > bool ret; > > + aio_disable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > ret = aio_poll(ctx, blocking); > + aio_enable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > return ret; This is not enough, because another thread's aio_poll can sneak in between calls to bdrv_aio_poll if the AioContext lock is released, and they will use the full set of clients. Similar to your v1, it works with the large critical sections we currently have, but it has the same problem in the longer term. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll Fam Zheng 2015-07-29 7:36 ` Paolo Bonzini @ 2015-07-29 7:37 ` Paolo Bonzini 2015-07-29 10:57 ` Fam Zheng 1 sibling, 1 reply; 54+ messages in thread From: Paolo Bonzini @ 2015-07-29 7:37 UTC (permalink / raw) To: Fam Zheng, qemu-devel; +Cc: kwolf, qemu-block, stefanha On 29/07/2015 06:42, Fam Zheng wrote: > @@ -2613,6 +2613,8 @@ bool bdrv_aio_poll(AioContext *ctx, bool blocking) > { > bool ret; > > + aio_disable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > ret = aio_poll(ctx, blocking); > + aio_enable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > return ret; This is not enough, because another thread's aio_poll can sneak in between calls to bdrv_aio_poll if the AioContext lock is released, and they will use the full set of clients. Similar to your v1, it works with the large critical sections we currently have, but it has the same problem in the longer term. The clients have to be disabled around calls to bdrv_drain, as you were doing when you had pause/resume notifiers. Patches 1-8 however are ok. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 7:37 ` Paolo Bonzini @ 2015-07-29 10:57 ` Fam Zheng 2015-07-29 11:02 ` Paolo Bonzini 0 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 10:57 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, stefanha, qemu-devel, qemu-block On Wed, 07/29 09:37, Paolo Bonzini wrote: > > > On 29/07/2015 06:42, Fam Zheng wrote: > > @@ -2613,6 +2613,8 @@ bool bdrv_aio_poll(AioContext *ctx, bool blocking) > > { > > bool ret; > > > > + aio_disable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > > ret = aio_poll(ctx, blocking); > > + aio_enable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > > return ret; > > This is not enough, because another thread's aio_poll can sneak in > between calls to bdrv_aio_poll if the AioContext lock is released, and > they will use the full set of clients. > > Similar to your v1, it works with the large critical sections we > currently have, but it has the same problem in the longer term. Can we add more disable/enable pairs around bdrv_drain on top? Fam > > The clients have to be disabled around calls to bdrv_drain, as you were > doing when you had pause/resume notifiers. Patches 1-8 however are ok. > > Paolo > ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 10:57 ` Fam Zheng @ 2015-07-29 11:02 ` Paolo Bonzini 2015-07-29 11:53 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Paolo Bonzini @ 2015-07-29 11:02 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, stefanha, qemu-devel, qemu-block On 29/07/2015 12:57, Fam Zheng wrote: > On Wed, 07/29 09:37, Paolo Bonzini wrote: >> >> >> On 29/07/2015 06:42, Fam Zheng wrote: >>> @@ -2613,6 +2613,8 @@ bool bdrv_aio_poll(AioContext *ctx, bool blocking) >>> { >>> bool ret; >>> >>> + aio_disable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); >>> ret = aio_poll(ctx, blocking); >>> + aio_enable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); >>> return ret; >> >> This is not enough, because another thread's aio_poll can sneak in >> between calls to bdrv_aio_poll if the AioContext lock is released, and >> they will use the full set of clients. >> >> Similar to your v1, it works with the large critical sections we >> currently have, but it has the same problem in the longer term. > > Can we add more disable/enable pairs around bdrv_drain on top? Yes, though I think you'd end up reverting patches 10 and 11 in the end. All 11 patches are okay, though it would be great if you could post the full series before this is applied. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 11:02 ` Paolo Bonzini @ 2015-07-29 11:53 ` Fam Zheng 2015-07-29 12:03 ` Paolo Bonzini 0 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-29 11:53 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, stefanha, qemu-devel, qemu-block On Wed, 07/29 13:02, Paolo Bonzini wrote: > > > On 29/07/2015 12:57, Fam Zheng wrote: > > On Wed, 07/29 09:37, Paolo Bonzini wrote: > >> > >> > >> On 29/07/2015 06:42, Fam Zheng wrote: > >>> @@ -2613,6 +2613,8 @@ bool bdrv_aio_poll(AioContext *ctx, bool blocking) > >>> { > >>> bool ret; > >>> > >>> + aio_disable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > >>> ret = aio_poll(ctx, blocking); > >>> + aio_enable_clients(ctx, AIO_CLIENT_DATAPLANE | AIO_CLIENT_NBD_SERVER); > >>> return ret; > >> > >> This is not enough, because another thread's aio_poll can sneak in > >> between calls to bdrv_aio_poll if the AioContext lock is released, and > >> they will use the full set of clients. > >> > >> Similar to your v1, it works with the large critical sections we > >> currently have, but it has the same problem in the longer term. > > > > Can we add more disable/enable pairs around bdrv_drain on top? > > Yes, though I think you'd end up reverting patches 10 and 11 in the end. We will add outer disable/enable pairs to prevent another threads's aio_poll from sneaking in between bdrv_aio_poll calls, but we needn't obsolete bdrv_aio_poll() because of that - it can be useful by itself. For example bdrv_aio_cancel shouldn't look at ioeventfd, otherwise it could spin for too long on high load. Does that make sense? Fam > > All 11 patches are okay, though it would be great if you could post the > full series before this is applied. > > Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 11:53 ` Fam Zheng @ 2015-07-29 12:03 ` Paolo Bonzini 2015-07-30 1:35 ` Fam Zheng 2015-09-09 3:22 ` Fam Zheng 0 siblings, 2 replies; 54+ messages in thread From: Paolo Bonzini @ 2015-07-29 12:03 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, stefanha, qemu-devel, qemu-block On 29/07/2015 13:53, Fam Zheng wrote: >> > Yes, though I think you'd end up reverting patches 10 and 11 in the end. > We will add outer disable/enable pairs to prevent another threads's aio_poll > from sneaking in between bdrv_aio_poll calls, but we needn't obsolete > bdrv_aio_poll() because of that - it can be useful by itself. For example > bdrv_aio_cancel shouldn't look at ioeventfd, otherwise it could spin for too > long on high load. Does that make sense? Did you mean bdrv_drain() (when it is not already surrounded by disable/enable pairs in the caller)? But yes, that makes sense. I'm not sure that it makes sense to disable/enable in places such as bdrv_pread. The caller's block, if any, should suffice. In this sense you'd end up reverting large parts of patch 10. Then you would have to see how many calls to bdrv_aio_poll are still there, and how many can be converted with no semantic change to aio_poll (e.g. there's no difference in qemu-img.c), and you'd end up reverting patches 9 and 11 too. But we can look at that later. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 12:03 ` Paolo Bonzini @ 2015-07-30 1:35 ` Fam Zheng 2015-07-30 13:22 ` Paolo Bonzini 2015-09-09 3:22 ` Fam Zheng 1 sibling, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-07-30 1:35 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, stefanha, qemu-devel, qemu-block On Wed, 07/29 14:03, Paolo Bonzini wrote: > > > On 29/07/2015 13:53, Fam Zheng wrote: > >> > Yes, though I think you'd end up reverting patches 10 and 11 in the end. > > We will add outer disable/enable pairs to prevent another threads's aio_poll > > from sneaking in between bdrv_aio_poll calls, but we needn't obsolete > > bdrv_aio_poll() because of that - it can be useful by itself. For example > > bdrv_aio_cancel shouldn't look at ioeventfd, otherwise it could spin for too > > long on high load. Does that make sense? > > Did you mean bdrv_drain() (when it is not already surrounded by > disable/enable pairs in the caller)? But yes, that makes sense. > > I'm not sure that it makes sense to disable/enable in places such as > bdrv_pread. The caller's block, if any, should suffice. In this sense > you'd end up reverting large parts of patch 10. > > Then you would have to see how many calls to bdrv_aio_poll are still > there, and how many can be converted with no semantic change to aio_poll > (e.g. there's no difference in qemu-img.c), and you'd end up reverting > patches 9 and 11 too. But we can look at that later. > Okay. There 19 bdrv_aio_poll()'s after this series: block.c bdrv_create block/curl.c curl_init_state block/io.c bdrv_drain block/io.c bdrv_drain_all block/io.c bdrv_prwv_co block/io.c bdrv_get_block_status_above block/io.c bdrv_aio_cancel block/io.c bdrv_flush block/io.c bdrv_discard block/io.c bdrv_flush_io_queue block/nfs.c nfs_get_allocated_file_size block/qed-table.c qed_read_l1_table_sync block/qed-table.c qed_write_l1_table_sync block/qed-table.c qed_read_l2_table_sync block/qed-table.c qed_write_l2_table_sync blockjob.c block_job_finish_sync include/block/block.h bdrv_get_stats qemu-img.c run_block_job qemu-io-cmds.c do_co_write_zeroes qemu-io-cmds.c wait_break_f Most of them make some sense to me, but not many make a real difference. The most important ones should be bdrv_drain* and bdrv_flush, and can be taken care of from caller side. Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-30 1:35 ` Fam Zheng @ 2015-07-30 13:22 ` Paolo Bonzini 0 siblings, 0 replies; 54+ messages in thread From: Paolo Bonzini @ 2015-07-30 13:22 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, stefanha, qemu-devel, qemu-block On 30/07/2015 03:35, Fam Zheng wrote: > block.c bdrv_create > block/curl.c curl_init_state > block/io.c bdrv_drain > block/io.c bdrv_drain_all > block/io.c bdrv_prwv_co > block/io.c bdrv_get_block_status_above > block/io.c bdrv_aio_cancel > block/io.c bdrv_flush > block/io.c bdrv_discard > block/io.c bdrv_flush_io_queue > block/nfs.c nfs_get_allocated_file_size > block/qed-table.c qed_read_l1_table_sync > block/qed-table.c qed_write_l1_table_sync > block/qed-table.c qed_read_l2_table_sync > block/qed-table.c qed_write_l2_table_sync > blockjob.c block_job_finish_sync > include/block/block.h bdrv_get_stats > qemu-img.c run_block_job > qemu-io-cmds.c do_co_write_zeroes > qemu-io-cmds.c wait_break_f > > Most of them make some sense to me, but not many make a real difference. The > most important ones should be bdrv_drain* and bdrv_flush, and can be taken care > of from caller side. Even just bdrv_drain*. bdrv_flush is okay with incoming requests, it should be handled in the caller side. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-07-29 12:03 ` Paolo Bonzini 2015-07-30 1:35 ` Fam Zheng @ 2015-09-09 3:22 ` Fam Zheng 2015-09-11 8:15 ` Paolo Bonzini 1 sibling, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-09 3:22 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, stefanha, qemu-devel, qemu-block On Wed, 07/29 14:03, Paolo Bonzini wrote: > > > On 29/07/2015 13:53, Fam Zheng wrote: > >> > Yes, though I think you'd end up reverting patches 10 and 11 in the end. > > We will add outer disable/enable pairs to prevent another threads's aio_poll > > from sneaking in between bdrv_aio_poll calls, but we needn't obsolete > > bdrv_aio_poll() because of that - it can be useful by itself. For example > > bdrv_aio_cancel shouldn't look at ioeventfd, otherwise it could spin for too > > long on high load. Does that make sense? > > Did you mean bdrv_drain() (when it is not already surrounded by > disable/enable pairs in the caller)? But yes, that makes sense. > > I'm not sure that it makes sense to disable/enable in places such as > bdrv_pread. The caller's block, if any, should suffice. In this sense > you'd end up reverting large parts of patch 10. > > Then you would have to see how many calls to bdrv_aio_poll are still > there, and how many can be converted with no semantic change to aio_poll > (e.g. there's no difference in qemu-img.c), and you'd end up reverting > patches 9 and 11 too. But we can look at that later. Another advantage for bdrv_aio_poll() is, in main loop we will not need a separate AioContext in changes like: http://patchwork.ozlabs.org/patch/514968/ Because nested aio_poll will automatically be limited to only process block layer events. My idea is to eventually let main loop use aio_poll, which means we would also move chardev onto it. It would be neat to put all fds of the main thread into a single AioContext. Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-09 3:22 ` Fam Zheng @ 2015-09-11 8:15 ` Paolo Bonzini 2015-09-11 9:14 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Paolo Bonzini @ 2015-09-11 8:15 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, stefanha, qemu-devel, qemu-block On 09/09/2015 05:22, Fam Zheng wrote: > Another advantage for bdrv_aio_poll() is, in main loop we will not need > a separate AioContext in changes like: > > http://patchwork.ozlabs.org/patch/514968/ > > Because nested aio_poll will automatically be limited to only process block > layer events. My idea is to eventually let main loop use aio_poll That would be a step back. Using GSource is useful because it lets you integrate libraries such as GTK+. Paolo > , which means > we would also move chardev onto it. It would be neat to put all fds of the main > thread into a single AioContext. ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 8:15 ` Paolo Bonzini @ 2015-09-11 9:14 ` Fam Zheng 2015-09-11 9:36 ` [Qemu-devel] [Qemu-block] " Alberto Garcia 0 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-11 9:14 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, stefanha, qemu-devel, qemu-block On Fri, 09/11 10:15, Paolo Bonzini wrote: > > > On 09/09/2015 05:22, Fam Zheng wrote: > > Another advantage for bdrv_aio_poll() is, in main loop we will not need > > a separate AioContext in changes like: > > > > http://patchwork.ozlabs.org/patch/514968/ > > > > Because nested aio_poll will automatically be limited to only process block > > layer events. My idea is to eventually let main loop use aio_poll > > That would be a step back. Using GSource is useful because it lets you > integrate libraries such as GTK+. Can we move GTK to a separate GSource thread? Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 9:14 ` Fam Zheng @ 2015-09-11 9:36 ` Alberto Garcia 2015-09-11 9:43 ` Daniel P. Berrange ` (2 more replies) 0 siblings, 3 replies; 54+ messages in thread From: Alberto Garcia @ 2015-09-11 9:36 UTC (permalink / raw) To: Fam Zheng, Paolo Bonzini; +Cc: kwolf, qemu-block, qemu-devel, stefanha On Fri 11 Sep 2015 11:14:33 AM CEST, Fam Zheng <famz@redhat.com> wrote: >> > Another advantage for bdrv_aio_poll() is, in main loop we will not >> > need a separate AioContext in changes like: >> > >> > http://patchwork.ozlabs.org/patch/514968/ >> > >> > Because nested aio_poll will automatically be limited to only >> > process block layer events. My idea is to eventually let main loop >> > use aio_poll >> >> That would be a step back. Using GSource is useful because it lets >> you integrate libraries such as GTK+. > > Can we move GTK to a separate GSource thread? I think that GTK should always run in the main thread, or at least the one running the default main loop / GMainContext. Berto ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 9:36 ` [Qemu-devel] [Qemu-block] " Alberto Garcia @ 2015-09-11 9:43 ` Daniel P. Berrange 2015-09-11 9:44 ` Fam Zheng 2015-09-11 9:45 ` Paolo Bonzini 2 siblings, 0 replies; 54+ messages in thread From: Daniel P. Berrange @ 2015-09-11 9:43 UTC (permalink / raw) To: Alberto Garcia Cc: kwolf, Fam Zheng, qemu-block, qemu-devel, stefanha, Paolo Bonzini On Fri, Sep 11, 2015 at 11:36:10AM +0200, Alberto Garcia wrote: > On Fri 11 Sep 2015 11:14:33 AM CEST, Fam Zheng <famz@redhat.com> wrote: > > >> > Another advantage for bdrv_aio_poll() is, in main loop we will not > >> > need a separate AioContext in changes like: > >> > > >> > http://patchwork.ozlabs.org/patch/514968/ > >> > > >> > Because nested aio_poll will automatically be limited to only > >> > process block layer events. My idea is to eventually let main loop > >> > use aio_poll > >> > >> That would be a step back. Using GSource is useful because it lets > >> you integrate libraries such as GTK+. > > > > Can we move GTK to a separate GSource thread? > > I think that GTK should always run in the main thread, or at least the > one running the default main loop / GMainContext. In theory GTK can run from a separate thread, but my experiance with GTK and threads is that you end up in a world of hurt if you try to anything except use the main thread, so I'd really recommend against it. Even if you do extensive testing locally, things still break across different GTK versions people have, so its just not worth the pain. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 9:36 ` [Qemu-devel] [Qemu-block] " Alberto Garcia 2015-09-11 9:43 ` Daniel P. Berrange @ 2015-09-11 9:44 ` Fam Zheng 2015-09-11 9:54 ` Paolo Bonzini 2015-09-11 9:45 ` Paolo Bonzini 2 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-11 9:44 UTC (permalink / raw) To: Alberto Garcia; +Cc: kwolf, Paolo Bonzini, stefanha, qemu-devel, qemu-block On Fri, 09/11 11:36, Alberto Garcia wrote: > On Fri 11 Sep 2015 11:14:33 AM CEST, Fam Zheng <famz@redhat.com> wrote: > > >> > Another advantage for bdrv_aio_poll() is, in main loop we will not > >> > need a separate AioContext in changes like: > >> > > >> > http://patchwork.ozlabs.org/patch/514968/ > >> > > >> > Because nested aio_poll will automatically be limited to only > >> > process block layer events. My idea is to eventually let main loop > >> > use aio_poll > >> > >> That would be a step back. Using GSource is useful because it lets > >> you integrate libraries such as GTK+. > > > > Can we move GTK to a separate GSource thread? > > I think that GTK should always run in the main thread, or at least the > one running the default main loop / GMainContext. Yeah it's basically GMainContext staying in the main thread and block/net/chardev I/O put in a new AioContext thread. Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 9:44 ` Fam Zheng @ 2015-09-11 9:54 ` Paolo Bonzini 2015-09-11 10:40 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Paolo Bonzini @ 2015-09-11 9:54 UTC (permalink / raw) To: Fam Zheng, Alberto Garcia; +Cc: kwolf, stefanha, qemu-devel, qemu-block On 11/09/2015 11:44, Fam Zheng wrote: > > > > That would be a step back. Using GSource is useful because it lets > > > > you integrate libraries such as GTK+. > > > > > > Can we move GTK to a separate GSource thread? > > > > I think that GTK should always run in the main thread, or at least the > > one running the default main loop / GMainContext. > > Yeah it's basically GMainContext staying in the main thread and > block/net/chardev I/O put in a new AioContext thread. Why? The point of an event loop is that you can multiplex everything on the same thread. Unless we have specific needs (e.g. scalability) one thread is the way to go and keep things simple. The tool we have for scalability is AioContext + dataplane threads, and because we _can_ integrate it into the main thread (AioContext is a GSource) we can write code once for the main thread and for external dataplane threads. Using AioContext instead of duplicating the code is great. Moving SLIRP to Win32 would get rid of all the duplicated select() code between aio-win32.c and main-loop.c. A lot of main-loop.c code can go away (probably not all because unlike glib we support nanosecond timeouts with TimerListGroup, but who knows). However, there is no need to deviate the event loop from the well-known, standardized glib architecture. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 9:54 ` Paolo Bonzini @ 2015-09-11 10:40 ` Fam Zheng 2015-09-11 10:46 ` Paolo Bonzini 0 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-11 10:40 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, stefanha, Alberto Garcia, qemu-devel, qemu-block On Fri, 09/11 11:54, Paolo Bonzini wrote: > > > On 11/09/2015 11:44, Fam Zheng wrote: > > > > > That would be a step back. Using GSource is useful because it lets > > > > > you integrate libraries such as GTK+. > > > > > > > > Can we move GTK to a separate GSource thread? > > > > > > I think that GTK should always run in the main thread, or at least the > > > one running the default main loop / GMainContext. > > > > Yeah it's basically GMainContext staying in the main thread and > > block/net/chardev I/O put in a new AioContext thread. > > Why? The point of an event loop is that you can multiplex everything on > the same thread. Unless we have specific needs (e.g. scalability) one > thread is the way to go and keep things simple. The reason is scalability. :) > > The tool we have for scalability is AioContext + dataplane threads, and > because we _can_ integrate it into the main thread (AioContext is a > GSource) we can write code once for the main thread and for external > dataplane threads. I don't think integrating with main thread or not is a problem, we can still use the same code as before, because the event loop code change should be transparent (see below). > > Using AioContext instead of duplicating the code is great. Moving SLIRP > to Win32 would get rid of all the duplicated select() code between > aio-win32.c and main-loop.c. A lot of main-loop.c code can go away > (probably not all because unlike glib we support nanosecond timeouts > with TimerListGroup, but who knows). > > However, there is no need to deviate the event loop from the well-known, > standardized glib architecture. Moving things to AIO isn't deviation, it's more about enabling of dataplane and epoll. That's why block was moved to AioContext, and I think we can do similar for net and serial, the difference is that as a start, they don't need to be fully BQL-free like virtio-blk and scsi. But by running in an aio_poll() loop, they can better performance because of epoll. I'm thinking about something like this: Main thread (GTK): g_main_run() New io thread (one per process, includes block, net, serial): while (true) { qemu_mutex_lock_iothread(); aio_poll(qemu_aio_context); qemu_mutex_unlock_iothread(); } Dataplane thread (one per "-object iothread", includes dataplane enabled devices): while (true) { aio_poll(iothread->ctx); } Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 10:40 ` Fam Zheng @ 2015-09-11 10:46 ` Paolo Bonzini 2015-09-11 11:01 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Paolo Bonzini @ 2015-09-11 10:46 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, stefanha, Alberto Garcia, qemu-devel, qemu-block On 11/09/2015 12:40, Fam Zheng wrote: > On Fri, 09/11 11:54, Paolo Bonzini wrote: >> >> >> On 11/09/2015 11:44, Fam Zheng wrote: >>>>>> That would be a step back. Using GSource is useful because it lets >>>>>> you integrate libraries such as GTK+. >>>>> >>>>> Can we move GTK to a separate GSource thread? >>>> >>>> I think that GTK should always run in the main thread, or at least the >>>> one running the default main loop / GMainContext. >>> >>> Yeah it's basically GMainContext staying in the main thread and >>> block/net/chardev I/O put in a new AioContext thread. >> >> Why? The point of an event loop is that you can multiplex everything on >> the same thread. Unless we have specific needs (e.g. scalability) one >> thread is the way to go and keep things simple. > > The reason is scalability. :) Scalability of what? If virtio-net or virtio-serial needs to be more scalable, putting all of them into a non-main-loop thread will not make things more scalable, because you have a single thread anyway. You'd need to go BQL-free and allow an arbitrary number. > Moving things to AIO isn't deviation, it's more about enabling of dataplane and > epoll. That's why block was moved to AioContext, and I think we can do similar > for net and serial, the difference is that as a start, they don't need to be > fully BQL-free like virtio-blk and scsi. But by running in an aio_poll() loop, > they can better performance because of epoll. Isn't that what your "iohandler.c with AioHandler" already does? True, it would be epoll-within-poll, not pure poll. But if you need epoll, you might as well go BQL-free. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 10:46 ` Paolo Bonzini @ 2015-09-11 11:01 ` Fam Zheng 2015-09-11 11:02 ` Paolo Bonzini 0 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-11 11:01 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, qemu-block, Alberto Garcia, qemu-devel, stefanha On Fri, 09/11 12:46, Paolo Bonzini wrote: > > > On 11/09/2015 12:40, Fam Zheng wrote: > > On Fri, 09/11 11:54, Paolo Bonzini wrote: > >> > >> > >> On 11/09/2015 11:44, Fam Zheng wrote: > >>>>>> That would be a step back. Using GSource is useful because it lets > >>>>>> you integrate libraries such as GTK+. > >>>>> > >>>>> Can we move GTK to a separate GSource thread? > >>>> > >>>> I think that GTK should always run in the main thread, or at least the > >>>> one running the default main loop / GMainContext. > >>> > >>> Yeah it's basically GMainContext staying in the main thread and > >>> block/net/chardev I/O put in a new AioContext thread. > >> > >> Why? The point of an event loop is that you can multiplex everything on > >> the same thread. Unless we have specific needs (e.g. scalability) one > >> thread is the way to go and keep things simple. > > > > The reason is scalability. :) > > Scalability of what? If virtio-net or virtio-serial needs to be more > scalable, putting all of them into a non-main-loop thread will not make > things more scalable, because you have a single thread anyway. You'd > need to go BQL-free and allow an arbitrary number. > > > Moving things to AIO isn't deviation, it's more about enabling of dataplane and > > epoll. That's why block was moved to AioContext, and I think we can do similar > > for net and serial, the difference is that as a start, they don't need to be > > fully BQL-free like virtio-blk and scsi. But by running in an aio_poll() loop, > > they can better performance because of epoll. > > Isn't that what your "iohandler.c with AioHandler" already does? True, > it would be epoll-within-poll, not pure poll. But if you need epoll, > you might as well go BQL-free. epoll-within-poll? Do you mean change the main event loop from: qemu_poll_ns([..., ioeventfd1, ioeventfd2, ..., ioeventfd99], ...) to qemu_poll_ns([epollfd], ...) where epollfd watches all the fds, and let the handler of epollfd do epoll_wait()? Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 11:01 ` Fam Zheng @ 2015-09-11 11:02 ` Paolo Bonzini 2015-09-11 11:12 ` Fam Zheng 0 siblings, 1 reply; 54+ messages in thread From: Paolo Bonzini @ 2015-09-11 11:02 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, qemu-block, Alberto Garcia, qemu-devel, stefanha On 11/09/2015 13:01, Fam Zheng wrote: > On Fri, 09/11 12:46, Paolo Bonzini wrote: >> >> >> On 11/09/2015 12:40, Fam Zheng wrote: >>> On Fri, 09/11 11:54, Paolo Bonzini wrote: >>>> >>>> >>>> On 11/09/2015 11:44, Fam Zheng wrote: >>>>>>>> That would be a step back. Using GSource is useful because it lets >>>>>>>> you integrate libraries such as GTK+. >>>>>>> >>>>>>> Can we move GTK to a separate GSource thread? >>>>>> >>>>>> I think that GTK should always run in the main thread, or at least the >>>>>> one running the default main loop / GMainContext. >>>>> >>>>> Yeah it's basically GMainContext staying in the main thread and >>>>> block/net/chardev I/O put in a new AioContext thread. >>>> >>>> Why? The point of an event loop is that you can multiplex everything on >>>> the same thread. Unless we have specific needs (e.g. scalability) one >>>> thread is the way to go and keep things simple. >>> >>> The reason is scalability. :) >> >> Scalability of what? If virtio-net or virtio-serial needs to be more >> scalable, putting all of them into a non-main-loop thread will not make >> things more scalable, because you have a single thread anyway. You'd >> need to go BQL-free and allow an arbitrary number. >> >>> Moving things to AIO isn't deviation, it's more about enabling of dataplane and >>> epoll. That's why block was moved to AioContext, and I think we can do similar >>> for net and serial, the difference is that as a start, they don't need to be >>> fully BQL-free like virtio-blk and scsi. But by running in an aio_poll() loop, >>> they can better performance because of epoll. >> >> Isn't that what your "iohandler.c with AioHandler" already does? True, >> it would be epoll-within-poll, not pure poll. But if you need epoll, >> you might as well go BQL-free. > > epoll-within-poll? Do you mean change the main event loop from: > > qemu_poll_ns([..., ioeventfd1, ioeventfd2, ..., ioeventfd99], ...) > > to > > qemu_poll_ns([epollfd], ...) > > where epollfd watches all the fds, and let the handler of epollfd do > epoll_wait()? I mean that glib's main loop (or os_host_main_loop_wait in main-loop.c) uses poll, and then the AioContext GSource uses epoll. Still, you have a constant (and low) number of file descriptors in the outer poll. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 11:02 ` Paolo Bonzini @ 2015-09-11 11:12 ` Fam Zheng 0 siblings, 0 replies; 54+ messages in thread From: Fam Zheng @ 2015-09-11 11:12 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, qemu-block, Alberto Garcia, qemu-devel, stefanha On Fri, 09/11 13:02, Paolo Bonzini wrote: > > > On 11/09/2015 13:01, Fam Zheng wrote: > > On Fri, 09/11 12:46, Paolo Bonzini wrote: > >> > >> > >> On 11/09/2015 12:40, Fam Zheng wrote: > >>> On Fri, 09/11 11:54, Paolo Bonzini wrote: > >>>> > >>>> > >>>> On 11/09/2015 11:44, Fam Zheng wrote: > >>>>>>>> That would be a step back. Using GSource is useful because it lets > >>>>>>>> you integrate libraries such as GTK+. > >>>>>>> > >>>>>>> Can we move GTK to a separate GSource thread? > >>>>>> > >>>>>> I think that GTK should always run in the main thread, or at least the > >>>>>> one running the default main loop / GMainContext. > >>>>> > >>>>> Yeah it's basically GMainContext staying in the main thread and > >>>>> block/net/chardev I/O put in a new AioContext thread. > >>>> > >>>> Why? The point of an event loop is that you can multiplex everything on > >>>> the same thread. Unless we have specific needs (e.g. scalability) one > >>>> thread is the way to go and keep things simple. > >>> > >>> The reason is scalability. :) > >> > >> Scalability of what? If virtio-net or virtio-serial needs to be more > >> scalable, putting all of them into a non-main-loop thread will not make > >> things more scalable, because you have a single thread anyway. You'd > >> need to go BQL-free and allow an arbitrary number. > >> > >>> Moving things to AIO isn't deviation, it's more about enabling of dataplane and > >>> epoll. That's why block was moved to AioContext, and I think we can do similar > >>> for net and serial, the difference is that as a start, they don't need to be > >>> fully BQL-free like virtio-blk and scsi. But by running in an aio_poll() loop, > >>> they can better performance because of epoll. > >> > >> Isn't that what your "iohandler.c with AioHandler" already does? True, > >> it would be epoll-within-poll, not pure poll. But if you need epoll, > >> you might as well go BQL-free. > > > > epoll-within-poll? Do you mean change the main event loop from: > > > > qemu_poll_ns([..., ioeventfd1, ioeventfd2, ..., ioeventfd99], ...) > > > > to > > > > qemu_poll_ns([epollfd], ...) > > > > where epollfd watches all the fds, and let the handler of epollfd do > > epoll_wait()? > > I mean that glib's main loop (or os_host_main_loop_wait in main-loop.c) > uses poll, and then the AioContext GSource uses epoll. Still, you have > a constant (and low) number of file descriptors in the outer poll. > OK, I think I get your idea, and it sounds good to me, thank you very much! ;-) Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll 2015-09-11 9:36 ` [Qemu-devel] [Qemu-block] " Alberto Garcia 2015-09-11 9:43 ` Daniel P. Berrange 2015-09-11 9:44 ` Fam Zheng @ 2015-09-11 9:45 ` Paolo Bonzini 2 siblings, 0 replies; 54+ messages in thread From: Paolo Bonzini @ 2015-09-11 9:45 UTC (permalink / raw) To: Alberto Garcia, Fam Zheng; +Cc: kwolf, qemu-block, qemu-devel, stefanha On 11/09/2015 11:36, Alberto Garcia wrote: > > > > Because nested aio_poll will automatically be limited to only > > > > process block layer events. My idea is to eventually let main loop > > > > use aio_poll > > > > > > That would be a step back. Using GSource is useful because it lets > > > you integrate libraries such as GTK+. > > > > Can we move GTK to a separate GSource thread? > > I think that GTK should always run in the main thread, or at least the > one running the default main loop / GMainContext. Agreed. The glib main loop is a positive thing, not a negative one. Paolo ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (10 preceding siblings ...) 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll Fam Zheng @ 2015-07-29 7:38 ` Paolo Bonzini 2015-08-28 11:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-09-11 10:39 ` [Qemu-devel] " Kevin Wolf 13 siblings, 0 replies; 54+ messages in thread From: Paolo Bonzini @ 2015-07-29 7:38 UTC (permalink / raw) To: Fam Zheng, qemu-devel; +Cc: kwolf, qemu-block, stefanha On 29/07/2015 06:42, Fam Zheng wrote: > v2: Switch to disable/enable model. [Paolo] > > Most existing nested aio_poll()'s in block layer are inconsiderate of > dispatching potential new r/w requests from ioeventfds and nbd exports, which > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > enforce atomicity due to aio_poll in bdrv_drain_all). > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > and nested AioContext (patches not posted to qemu-devel). > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > is introducing "aio_context_disable_client / aio_context_enable_client to > filter AioContext handlers according to the "client", e.g. > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > client (type)." > > After this series, block layer aio_poll() will only process those "protocol" > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > aio_poll()'s keep unchanged. > > The biggest advantage over approaches [1] and [2] is, no change is needed in > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > coroutines. > > The windows implementation is not tested except for compiling. > > [1]: https://lists.gnu.org/archive/html/qemu-block/2015-05/msg00800.html > [2]: http://lists.nongnu.org/archive/html/qemu-block/2015-06/msg00027.html For patches 1-8: Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (11 preceding siblings ...) 2015-07-29 7:38 ` [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Paolo Bonzini @ 2015-08-28 11:53 ` Stefan Hajnoczi 2015-09-07 6:28 ` Fam Zheng 2015-09-11 10:39 ` [Qemu-devel] " Kevin Wolf 13 siblings, 1 reply; 54+ messages in thread From: Stefan Hajnoczi @ 2015-08-28 11:53 UTC (permalink / raw) To: Fam Zheng; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Wed, Jul 29, 2015 at 12:42:03PM +0800, Fam Zheng wrote: > v2: Switch to disable/enable model. [Paolo] > > Most existing nested aio_poll()'s in block layer are inconsiderate of > dispatching potential new r/w requests from ioeventfds and nbd exports, which > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > enforce atomicity due to aio_poll in bdrv_drain_all). > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > and nested AioContext (patches not posted to qemu-devel). > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > is introducing "aio_context_disable_client / aio_context_enable_client to > filter AioContext handlers according to the "client", e.g. > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > client (type)." > > After this series, block layer aio_poll() will only process those "protocol" > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > aio_poll()'s keep unchanged. > > The biggest advantage over approaches [1] and [2] is, no change is needed in > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > coroutines. > > The windows implementation is not tested except for compiling. > > [1]: https://lists.gnu.org/archive/html/qemu-block/2015-05/msg00800.html > [2]: http://lists.nongnu.org/archive/html/qemu-block/2015-06/msg00027.html > > > Fam Zheng (11): > aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier > aio: Save type to AioHandler > block: Mark fd handlers as "protocol" > nbd: Mark fd handlers client type as "nbd server" > aio: Mark ctx->notifier's client type as "context" > dataplane: Mark host notifiers' client type as "dataplane" > aio-posix: introduce aio_{disable,enable}_clients > aio-win32: Implement aio_{disable,enable}_clients > block: Introduce bdrv_aio_poll > block: Replace nested aio_poll with bdrv_aio_poll > block: Only poll block layer fds in bdrv_aio_poll > > aio-posix.c | 23 ++++++++++++++-- > aio-win32.c | 22 +++++++++++++++- > async.c | 3 ++- > block.c | 2 +- > block/curl.c | 16 +++++++----- > block/io.c | 28 +++++++++++++------- > block/iscsi.c | 9 +++---- > block/linux-aio.c | 5 ++-- > block/nbd-client.c | 10 ++++--- > block/nfs.c | 19 ++++++-------- > block/qed-table.c | 8 +++--- > block/sheepdog.c | 32 +++++++++++++++-------- > block/ssh.c | 5 ++-- > block/win32-aio.c | 5 ++-- > blockjob.c | 2 +- > hw/block/dataplane/virtio-blk.c | 6 +++-- > hw/scsi/virtio-scsi-dataplane.c | 24 +++++++++++------ > include/block/aio.h | 33 +++++++++++++++++++++++ > include/block/block.h | 2 ++ > nbd.c | 4 ++- > qemu-img.c | 2 +- > qemu-io-cmds.c | 4 +-- > tests/test-aio.c | 58 +++++++++++++++++++++++------------------ > 23 files changed, 219 insertions(+), 103 deletions(-) What is the status of this series? Paolo's points about Patch 11 & 12 stand. It seems the fd type concept is good but the bdrv_aio_poll() mechanism requires changes to fully solve the problem. Stefan ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-08-28 11:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi @ 2015-09-07 6:28 ` Fam Zheng 0 siblings, 0 replies; 54+ messages in thread From: Fam Zheng @ 2015-09-07 6:28 UTC (permalink / raw) To: Stefan Hajnoczi; +Cc: kwolf, pbonzini, qemu-block, qemu-devel, stefanha On Fri, 08/28 12:53, Stefan Hajnoczi wrote: > On Wed, Jul 29, 2015 at 12:42:03PM +0800, Fam Zheng wrote: > > v2: Switch to disable/enable model. [Paolo] > > > > Most existing nested aio_poll()'s in block layer are inconsiderate of > > dispatching potential new r/w requests from ioeventfds and nbd exports, which > > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > > enforce atomicity due to aio_poll in bdrv_drain_all). > > > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > > and nested AioContext (patches not posted to qemu-devel). > > > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > > is introducing "aio_context_disable_client / aio_context_enable_client to > > filter AioContext handlers according to the "client", e.g. > > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > > client (type)." > > > > After this series, block layer aio_poll() will only process those "protocol" > > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > > aio_poll()'s keep unchanged. > > > > The biggest advantage over approaches [1] and [2] is, no change is needed in > > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > > coroutines. > > > > The windows implementation is not tested except for compiling. > > > > [1]: https://lists.gnu.org/archive/html/qemu-block/2015-05/msg00800.html > > [2]: http://lists.nongnu.org/archive/html/qemu-block/2015-06/msg00027.html > > > > > > Fam Zheng (11): > > aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier > > aio: Save type to AioHandler > > block: Mark fd handlers as "protocol" > > nbd: Mark fd handlers client type as "nbd server" > > aio: Mark ctx->notifier's client type as "context" > > dataplane: Mark host notifiers' client type as "dataplane" > > aio-posix: introduce aio_{disable,enable}_clients > > aio-win32: Implement aio_{disable,enable}_clients > > block: Introduce bdrv_aio_poll > > block: Replace nested aio_poll with bdrv_aio_poll > > block: Only poll block layer fds in bdrv_aio_poll > > > > aio-posix.c | 23 ++++++++++++++-- > > aio-win32.c | 22 +++++++++++++++- > > async.c | 3 ++- > > block.c | 2 +- > > block/curl.c | 16 +++++++----- > > block/io.c | 28 +++++++++++++------- > > block/iscsi.c | 9 +++---- > > block/linux-aio.c | 5 ++-- > > block/nbd-client.c | 10 ++++--- > > block/nfs.c | 19 ++++++-------- > > block/qed-table.c | 8 +++--- > > block/sheepdog.c | 32 +++++++++++++++-------- > > block/ssh.c | 5 ++-- > > block/win32-aio.c | 5 ++-- > > blockjob.c | 2 +- > > hw/block/dataplane/virtio-blk.c | 6 +++-- > > hw/scsi/virtio-scsi-dataplane.c | 24 +++++++++++------ > > include/block/aio.h | 33 +++++++++++++++++++++++ > > include/block/block.h | 2 ++ > > nbd.c | 4 ++- > > qemu-img.c | 2 +- > > qemu-io-cmds.c | 4 +-- > > tests/test-aio.c | 58 +++++++++++++++++++++++------------------ > > 23 files changed, 219 insertions(+), 103 deletions(-) > > What is the status of this series? > > Paolo's points about Patch 11 & 12 stand. It seems the fd type concept > is good but the bdrv_aio_poll() mechanism requires changes to fully > solve the problem. Let's drop bdrv_aio_poll(), introduce bdrv_quiesce() and bdrv_unquiesce() to protect nested aio_poll(). For example in QMP, add them between prepare and commit. That needs more changes, like splitting drive_backup_prepare() and put the starting of coroutine and installing of "before_write" notifier to BdrvActionOps.commit. Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng ` (12 preceding siblings ...) 2015-08-28 11:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi @ 2015-09-11 10:39 ` Kevin Wolf 2015-09-11 11:46 ` Fam Zheng 13 siblings, 1 reply; 54+ messages in thread From: Kevin Wolf @ 2015-09-11 10:39 UTC (permalink / raw) To: Fam Zheng; +Cc: pbonzini, stefanha, qemu-devel, qemu-block Am 29.07.2015 um 06:42 hat Fam Zheng geschrieben: > v2: Switch to disable/enable model. [Paolo] > > Most existing nested aio_poll()'s in block layer are inconsiderate of > dispatching potential new r/w requests from ioeventfds and nbd exports, which > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > enforce atomicity due to aio_poll in bdrv_drain_all). > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > and nested AioContext (patches not posted to qemu-devel). > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > is introducing "aio_context_disable_client / aio_context_enable_client to > filter AioContext handlers according to the "client", e.g. > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > client (type)." > > After this series, block layer aio_poll() will only process those "protocol" > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > aio_poll()'s keep unchanged. > > The biggest advantage over approaches [1] and [2] is, no change is needed in > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > coroutines. It seems that I haven't replied on the mailing list yet, even though I think I already said this in person at KVM Forum: This series fixes only a special case of the real problem, which is that bdrv_drain/all at a single point doesn't make a lot of sense, but needs to be replaced by a whole section with exclusive access, like a bdrv_drained_begin/end pair. To be clear: Anything that works with types of users instead of individual users is bound to fall short of being a complete solution. I don't prefer partial solutions when we know there is a bigger problem. This series addresses your immediate need of protecting against new data plane requests, which it arguably achieves. The second case I always have in mind is Berto's case where he has multiple streaming block jobs in the same backing file chain [1]. This involves a bdrv_reopen() of the target BDS to make it writable, and bdrv_reopen() uses bdrv_drain_all() so drivers don't have to cope with running requests while reopening themselves. It can however involve nested event loops for synchronous operations like bdrv_flush(), and if those can process completions of block jobs, which can respond by doing anything to the respective node, things can go wrong. You don't solve this by adding client types (then problematic request would be PROTOCOL in your proposal and you can never exclude that), but you really need to have bdrv_drained_being/end pairs, where only requests issued in between are processed and everything else waits. Kevin [1] https://lists.gnu.org/archive/html/qemu-devel/2015-06/msg06273.html ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-09-11 10:39 ` [Qemu-devel] " Kevin Wolf @ 2015-09-11 11:46 ` Fam Zheng 2015-09-11 12:22 ` Kevin Wolf 0 siblings, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-11 11:46 UTC (permalink / raw) To: Kevin Wolf; +Cc: pbonzini, qemu-block, qemu-devel, stefanha On Fri, 09/11 12:39, Kevin Wolf wrote: > Am 29.07.2015 um 06:42 hat Fam Zheng geschrieben: > > v2: Switch to disable/enable model. [Paolo] > > > > Most existing nested aio_poll()'s in block layer are inconsiderate of > > dispatching potential new r/w requests from ioeventfds and nbd exports, which > > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > > enforce atomicity due to aio_poll in bdrv_drain_all). > > > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > > and nested AioContext (patches not posted to qemu-devel). > > > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > > is introducing "aio_context_disable_client / aio_context_enable_client to > > filter AioContext handlers according to the "client", e.g. > > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > > client (type)." > > > > After this series, block layer aio_poll() will only process those "protocol" > > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > > aio_poll()'s keep unchanged. > > > > The biggest advantage over approaches [1] and [2] is, no change is needed in > > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > > coroutines. > > It seems that I haven't replied on the mailing list yet, even though I > think I already said this in person at KVM Forum: This series fixes only > a special case of the real problem, which is that bdrv_drain/all at a > single point doesn't make a lot of sense, but needs to be replaced by a > whole section with exclusive access, like a bdrv_drained_begin/end pair. > > To be clear: Anything that works with types of users instead of > individual users is bound to fall short of being a complete solution. I > don't prefer partial solutions when we know there is a bigger problem. > > This series addresses your immediate need of protecting against new data > plane requests, which it arguably achieves. The second case I always > have in mind is Berto's case where he has multiple streaming block jobs > in the same backing file chain [1]. > > This involves a bdrv_reopen() of the target BDS to make it writable, and > bdrv_reopen() uses bdrv_drain_all() so drivers don't have to cope with > running requests while reopening themselves. It can however involve > nested event loops for synchronous operations like bdrv_flush(), and if > those can process completions of block jobs, which can respond by doing > anything to the respective node, things can go wrong. Just to get a better idea of bdrv_drained_begin/end, could you explain how to use the pair to fix the above problem? > > You don't solve this by adding client types (then problematic request > would be PROTOCOL in your proposal and you can never exclude that), but > you really need to have bdrv_drained_being/end pairs, where only > requests issued in between are processed and everything else waits. What do you mean by "only requests issued in between are processed"? Where are the requests from? Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-09-11 11:46 ` Fam Zheng @ 2015-09-11 12:22 ` Kevin Wolf 2015-09-14 7:27 ` Fam Zheng 2015-09-28 9:31 ` Stefan Hajnoczi 0 siblings, 2 replies; 54+ messages in thread From: Kevin Wolf @ 2015-09-11 12:22 UTC (permalink / raw) To: Fam Zheng; +Cc: pbonzini, qemu-block, qemu-devel, stefanha Am 11.09.2015 um 13:46 hat Fam Zheng geschrieben: > On Fri, 09/11 12:39, Kevin Wolf wrote: > > Am 29.07.2015 um 06:42 hat Fam Zheng geschrieben: > > > v2: Switch to disable/enable model. [Paolo] > > > > > > Most existing nested aio_poll()'s in block layer are inconsiderate of > > > dispatching potential new r/w requests from ioeventfds and nbd exports, which > > > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > > > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > > > enforce atomicity due to aio_poll in bdrv_drain_all). > > > > > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > > > and nested AioContext (patches not posted to qemu-devel). > > > > > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > > > is introducing "aio_context_disable_client / aio_context_enable_client to > > > filter AioContext handlers according to the "client", e.g. > > > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > > > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > > > client (type)." > > > > > > After this series, block layer aio_poll() will only process those "protocol" > > > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > > > aio_poll()'s keep unchanged. > > > > > > The biggest advantage over approaches [1] and [2] is, no change is needed in > > > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > > > coroutines. > > > > It seems that I haven't replied on the mailing list yet, even though I > > think I already said this in person at KVM Forum: This series fixes only > > a special case of the real problem, which is that bdrv_drain/all at a > > single point doesn't make a lot of sense, but needs to be replaced by a > > whole section with exclusive access, like a bdrv_drained_begin/end pair. > > > > To be clear: Anything that works with types of users instead of > > individual users is bound to fall short of being a complete solution. I > > don't prefer partial solutions when we know there is a bigger problem. > > > > This series addresses your immediate need of protecting against new data > > plane requests, which it arguably achieves. The second case I always > > have in mind is Berto's case where he has multiple streaming block jobs > > in the same backing file chain [1]. > > > > This involves a bdrv_reopen() of the target BDS to make it writable, and > > bdrv_reopen() uses bdrv_drain_all() so drivers don't have to cope with > > running requests while reopening themselves. It can however involve > > nested event loops for synchronous operations like bdrv_flush(), and if > > those can process completions of block jobs, which can respond by doing > > anything to the respective node, things can go wrong. > > Just to get a better idea of bdrv_drained_begin/end, could you explain how to > use the pair to fix the above problem? How to use it is easy part: In bdrv_reopen_multiple(), you would replace the existing bdrv_drain_all() with begin and you would add the corresponding end right before the return statement. > > You don't solve this by adding client types (then problematic request > > would be PROTOCOL in your proposal and you can never exclude that), but > > you really need to have bdrv_drained_being/end pairs, where only > > requests issued in between are processed and everything else waits. > > What do you mean by "only requests issued in between are processed"? Where are > the requests from? Generally speaking, you would have code that looks like this: bdrv_drain_begin() ... bdrv_something_synchronous() ... bdrv_drain_end() You want to process everything that is necessary for completing bdrv_something_synchronous(), but nothing else. The trickier question is how to implement this. I know that it's much easier to say that your series doesn't work than actually proposing something else that works... One relatively obvious answer we found when we discussed this a while back was some kind of a recursive CoRwLock (reader = in-flight request; writer = drained section), but that requires obviously that you're running in a coroutine if you want to do something with a drained request queue. I'm also not totally happy with the requirement of taking a reader lock more or less everywhere. But I'm not sure yet if there is a good alternative that can achieve the same. This needs some more thought, I guess. Kevin ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-09-11 12:22 ` Kevin Wolf @ 2015-09-14 7:27 ` Fam Zheng 2015-09-14 8:40 ` Kevin Wolf 2015-09-28 9:31 ` Stefan Hajnoczi 1 sibling, 1 reply; 54+ messages in thread From: Fam Zheng @ 2015-09-14 7:27 UTC (permalink / raw) To: Kevin Wolf; +Cc: pbonzini, stefanha, qemu-devel, qemu-block On Fri, 09/11 14:22, Kevin Wolf wrote: > Am 11.09.2015 um 13:46 hat Fam Zheng geschrieben: > > On Fri, 09/11 12:39, Kevin Wolf wrote: > > > Am 29.07.2015 um 06:42 hat Fam Zheng geschrieben: > > > > v2: Switch to disable/enable model. [Paolo] > > > > > > > > Most existing nested aio_poll()'s in block layer are inconsiderate of > > > > dispatching potential new r/w requests from ioeventfds and nbd exports, which > > > > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > > > > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > > > > enforce atomicity due to aio_poll in bdrv_drain_all). > > > > > > > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > > > > and nested AioContext (patches not posted to qemu-devel). > > > > > > > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > > > > is introducing "aio_context_disable_client / aio_context_enable_client to > > > > filter AioContext handlers according to the "client", e.g. > > > > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > > > > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > > > > client (type)." > > > > > > > > After this series, block layer aio_poll() will only process those "protocol" > > > > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > > > > aio_poll()'s keep unchanged. > > > > > > > > The biggest advantage over approaches [1] and [2] is, no change is needed in > > > > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > > > > coroutines. > > > > > > It seems that I haven't replied on the mailing list yet, even though I > > > think I already said this in person at KVM Forum: This series fixes only > > > a special case of the real problem, which is that bdrv_drain/all at a > > > single point doesn't make a lot of sense, but needs to be replaced by a > > > whole section with exclusive access, like a bdrv_drained_begin/end pair. > > > > > > To be clear: Anything that works with types of users instead of > > > individual users is bound to fall short of being a complete solution. I > > > don't prefer partial solutions when we know there is a bigger problem. > > > > > > This series addresses your immediate need of protecting against new data > > > plane requests, which it arguably achieves. The second case I always > > > have in mind is Berto's case where he has multiple streaming block jobs > > > in the same backing file chain [1]. > > > > > > This involves a bdrv_reopen() of the target BDS to make it writable, and > > > bdrv_reopen() uses bdrv_drain_all() so drivers don't have to cope with > > > running requests while reopening themselves. It can however involve > > > nested event loops for synchronous operations like bdrv_flush(), and if > > > those can process completions of block jobs, which can respond by doing > > > anything to the respective node, things can go wrong. > > > > Just to get a better idea of bdrv_drained_begin/end, could you explain how to > > use the pair to fix the above problem? > > How to use it is easy part: In bdrv_reopen_multiple(), you would replace > the existing bdrv_drain_all() with begin and you would add the > corresponding end right before the return statement. OK, so that the completion of other jobs won't happen because we only complete the relevant requests? Does block_job_pause() work here? > > > > You don't solve this by adding client types (then problematic request > > > would be PROTOCOL in your proposal and you can never exclude that), but > > > you really need to have bdrv_drained_being/end pairs, where only > > > requests issued in between are processed and everything else waits. > > > > What do you mean by "only requests issued in between are processed"? Where are > > the requests from? > > Generally speaking, you would have code that looks like this: > > bdrv_drain_begin() > ... > bdrv_something_synchronous() > ... > bdrv_drain_end() > > You want to process everything that is necessary for completing > bdrv_something_synchronous(), but nothing else. > > The trickier question is how to implement this. I know that it's much > easier to say that your series doesn't work than actually proposing > something else that works... I see the basic idea but that is still way too obscure. How would bdrv_draind_begin/end know what is necessary in completing bdrv_something_synchronous()? > > One relatively obvious answer we found when we discussed this a while > back was some kind of a recursive CoRwLock (reader = in-flight request; > writer = drained section), but that requires obviously that you're > running in a coroutine if you want to do something with a drained > request queue. > > I'm also not totally happy with the requirement of taking a reader lock > more or less everywhere. But I'm not sure yet if there is a good > alternative that can achieve the same. We're basically trying to prevent new requests from being submitted, but couldn't this blocking be a complication itself? A CoRwLock, if any, would be implemented with something like a CoQueue, but considering the existing CoQueue in BDS - throttled_reqs, aren't those what we want to keep *empty* between the bdrv_drain_begin/end pair? Now we're talking about queueing requests to another CoQueue, which feels contradictory to me. Fam ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-09-14 7:27 ` Fam Zheng @ 2015-09-14 8:40 ` Kevin Wolf 0 siblings, 0 replies; 54+ messages in thread From: Kevin Wolf @ 2015-09-14 8:40 UTC (permalink / raw) To: Fam Zheng; +Cc: pbonzini, stefanha, qemu-devel, qemu-block Am 14.09.2015 um 09:27 hat Fam Zheng geschrieben: > On Fri, 09/11 14:22, Kevin Wolf wrote: > > Am 11.09.2015 um 13:46 hat Fam Zheng geschrieben: > > > On Fri, 09/11 12:39, Kevin Wolf wrote: > > > > Am 29.07.2015 um 06:42 hat Fam Zheng geschrieben: > > > > > v2: Switch to disable/enable model. [Paolo] > > > > > > > > > > Most existing nested aio_poll()'s in block layer are inconsiderate of > > > > > dispatching potential new r/w requests from ioeventfds and nbd exports, which > > > > > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > > > > > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > > > > > enforce atomicity due to aio_poll in bdrv_drain_all). > > > > > > > > > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > > > > > and nested AioContext (patches not posted to qemu-devel). > > > > > > > > > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > > > > > is introducing "aio_context_disable_client / aio_context_enable_client to > > > > > filter AioContext handlers according to the "client", e.g. > > > > > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > > > > > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > > > > > client (type)." > > > > > > > > > > After this series, block layer aio_poll() will only process those "protocol" > > > > > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > > > > > aio_poll()'s keep unchanged. > > > > > > > > > > The biggest advantage over approaches [1] and [2] is, no change is needed in > > > > > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > > > > > coroutines. > > > > > > > > It seems that I haven't replied on the mailing list yet, even though I > > > > think I already said this in person at KVM Forum: This series fixes only > > > > a special case of the real problem, which is that bdrv_drain/all at a > > > > single point doesn't make a lot of sense, but needs to be replaced by a > > > > whole section with exclusive access, like a bdrv_drained_begin/end pair. > > > > > > > > To be clear: Anything that works with types of users instead of > > > > individual users is bound to fall short of being a complete solution. I > > > > don't prefer partial solutions when we know there is a bigger problem. > > > > > > > > This series addresses your immediate need of protecting against new data > > > > plane requests, which it arguably achieves. The second case I always > > > > have in mind is Berto's case where he has multiple streaming block jobs > > > > in the same backing file chain [1]. > > > > > > > > This involves a bdrv_reopen() of the target BDS to make it writable, and > > > > bdrv_reopen() uses bdrv_drain_all() so drivers don't have to cope with > > > > running requests while reopening themselves. It can however involve > > > > nested event loops for synchronous operations like bdrv_flush(), and if > > > > those can process completions of block jobs, which can respond by doing > > > > anything to the respective node, things can go wrong. > > > > > > Just to get a better idea of bdrv_drained_begin/end, could you explain how to > > > use the pair to fix the above problem? > > > > How to use it is easy part: In bdrv_reopen_multiple(), you would replace > > the existing bdrv_drain_all() with begin and you would add the > > corresponding end right before the return statement. > > OK, so that the completion of other jobs won't happen because we only complete > the relevant requests? > > Does block_job_pause() work here? If you find all block jobs that do something with the BDS, block_job_pause() would work, yes. But if you go further down that road, you end up not with a design that considers the problem, but with special casing every single user. That doesn't feel very sustainable. > > > > You don't solve this by adding client types (then problematic request > > > > would be PROTOCOL in your proposal and you can never exclude that), but > > > > you really need to have bdrv_drained_being/end pairs, where only > > > > requests issued in between are processed and everything else waits. > > > > > > What do you mean by "only requests issued in between are processed"? Where are > > > the requests from? > > > > Generally speaking, you would have code that looks like this: > > > > bdrv_drain_begin() > > ... > > bdrv_something_synchronous() > > ... > > bdrv_drain_end() > > > > You want to process everything that is necessary for completing > > bdrv_something_synchronous(), but nothing else. > > > > The trickier question is how to implement this. I know that it's much > > easier to say that your series doesn't work than actually proposing > > something else that works... > > I see the basic idea but that is still way too obscure. How would > bdrv_draind_begin/end know what is necessary in completing > bdrv_something_synchronous()? That's not about the interface, but the implementation part, which I tried to answer below. > > One relatively obvious answer we found when we discussed this a while > > back was some kind of a recursive CoRwLock (reader = in-flight request; > > writer = drained section), but that requires obviously that you're > > running in a coroutine if you want to do something with a drained > > request queue. > > > > I'm also not totally happy with the requirement of taking a reader lock > > more or less everywhere. But I'm not sure yet if there is a good > > alternative that can achieve the same. > > We're basically trying to prevent new requests from being submitted, but > couldn't this blocking be a complication itself? A CoRwLock, if any, would be > implemented with something like a CoQueue, but considering the existing CoQueue > in BDS - throttled_reqs, aren't those what we want to keep *empty* between the > bdrv_drain_begin/end pair? Now we're talking about queueing requests to > another CoQueue, which feels contradictory to me. You always queue requests _somewhere_. If they aren't queued in the block layer, they are in the virtio ring or elsewhere. I think the point of bdrv_drain() is that the block drivers don't have any pending requests; they can be queued elsewhere without hurting anyone. Kevin ^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane 2015-09-11 12:22 ` Kevin Wolf 2015-09-14 7:27 ` Fam Zheng @ 2015-09-28 9:31 ` Stefan Hajnoczi 1 sibling, 0 replies; 54+ messages in thread From: Stefan Hajnoczi @ 2015-09-28 9:31 UTC (permalink / raw) To: Kevin Wolf; +Cc: pbonzini, Fam Zheng, qemu-devel, qemu-block On Fri, Sep 11, 2015 at 02:22:14PM +0200, Kevin Wolf wrote: > Am 11.09.2015 um 13:46 hat Fam Zheng geschrieben: > > On Fri, 09/11 12:39, Kevin Wolf wrote: > > > Am 29.07.2015 um 06:42 hat Fam Zheng geschrieben: > > > > v2: Switch to disable/enable model. [Paolo] > > > > > > > > Most existing nested aio_poll()'s in block layer are inconsiderate of > > > > dispatching potential new r/w requests from ioeventfds and nbd exports, which > > > > might result in responsiveness issues (e.g. bdrv_drain_all will not return when > > > > new requests keep coming), or even wrong semantics (e.g. qmp_transaction cannot > > > > enforce atomicity due to aio_poll in bdrv_drain_all). > > > > > > > > Previous attampts to address this issue include new op blocker[1], bdrv_lock[2] > > > > and nested AioContext (patches not posted to qemu-devel). > > > > > > > > This approach is based on the idea proposed by Paolo Bonzini. The original idea > > > > is introducing "aio_context_disable_client / aio_context_enable_client to > > > > filter AioContext handlers according to the "client", e.g. > > > > AIO_CLIENT_DATAPLANE (ioeventfd), AIO_CLIENT_PROTOCOL, AIO_CLIENT_NBD_SERVER, > > > > AIO_CLIENT_CONTEXT, ... Extend aio_set_{event_notifier,fd}_handler to pass a > > > > client (type)." > > > > > > > > After this series, block layer aio_poll() will only process those "protocol" > > > > fds that are used in block I/O, plus the ctx->notifier for aio_notify(); other > > > > aio_poll()'s keep unchanged. > > > > > > > > The biggest advantage over approaches [1] and [2] is, no change is needed in > > > > virtio-{blk,scsi}-dataplane code, also this doesn't depend on converting QMP to > > > > coroutines. > > > > > > It seems that I haven't replied on the mailing list yet, even though I > > > think I already said this in person at KVM Forum: This series fixes only > > > a special case of the real problem, which is that bdrv_drain/all at a > > > single point doesn't make a lot of sense, but needs to be replaced by a > > > whole section with exclusive access, like a bdrv_drained_begin/end pair. > > > > > > To be clear: Anything that works with types of users instead of > > > individual users is bound to fall short of being a complete solution. I > > > don't prefer partial solutions when we know there is a bigger problem. > > > > > > This series addresses your immediate need of protecting against new data > > > plane requests, which it arguably achieves. The second case I always > > > have in mind is Berto's case where he has multiple streaming block jobs > > > in the same backing file chain [1]. > > > > > > This involves a bdrv_reopen() of the target BDS to make it writable, and > > > bdrv_reopen() uses bdrv_drain_all() so drivers don't have to cope with > > > running requests while reopening themselves. It can however involve > > > nested event loops for synchronous operations like bdrv_flush(), and if > > > those can process completions of block jobs, which can respond by doing > > > anything to the respective node, things can go wrong. > > > > Just to get a better idea of bdrv_drained_begin/end, could you explain how to > > use the pair to fix the above problem? > > How to use it is easy part: In bdrv_reopen_multiple(), you would replace > the existing bdrv_drain_all() with begin and you would add the > corresponding end right before the return statement. > > > > You don't solve this by adding client types (then problematic request > > > would be PROTOCOL in your proposal and you can never exclude that), but > > > you really need to have bdrv_drained_being/end pairs, where only > > > requests issued in between are processed and everything else waits. > > > > What do you mean by "only requests issued in between are processed"? Where are > > the requests from? > > Generally speaking, you would have code that looks like this: > > bdrv_drain_begin() > ... > bdrv_something_synchronous() > ... > bdrv_drain_end() > > You want to process everything that is necessary for completing > bdrv_something_synchronous(), but nothing else. > > The trickier question is how to implement this. I know that it's much > easier to say that your series doesn't work than actually proposing > something else that works... > > One relatively obvious answer we found when we discussed this a while > back was some kind of a recursive CoRwLock (reader = in-flight request; > writer = drained section), but that requires obviously that you're > running in a coroutine if you want to do something with a drained > request queue. At one point I thought about converting vl.c:main() to run everything in a coroutine. It would allow us to eliminate synchronous operations completely. The problem is that it's quite a big change that requires protecting formerly synchronous operations against concurrency. Stefan ^ permalink raw reply [flat|nested] 54+ messages in thread
end of thread, other threads:[~2015-09-28 9:31 UTC | newest] Thread overview: 54+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-07-29 4:42 [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 01/11] aio: Introduce "type" in aio_set_fd_handler and aio_set_event_notifier Fam Zheng 2015-08-27 13:50 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 02/11] aio: Save type to AioHandler Fam Zheng 2015-08-27 13:50 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 03/11] block: Mark fd handlers as "protocol" Fam Zheng 2015-08-27 13:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-09-07 4:43 ` Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 04/11] nbd: Mark fd handlers client type as "nbd server" Fam Zheng 2015-08-27 14:02 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 05/11] aio: Mark ctx->notifier's client type as "context" Fam Zheng 2015-08-27 17:12 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 06/11] dataplane: Mark host notifiers' client type as "dataplane" Fam Zheng 2015-08-27 17:14 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 07/11] aio-posix: introduce aio_{disable, enable}_clients Fam Zheng 2015-08-27 17:23 ` Stefan Hajnoczi 2015-09-07 5:26 ` Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 08/11] aio-win32: Implement " Fam Zheng 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 09/11] block: Introduce bdrv_aio_poll Fam Zheng 2015-08-27 17:25 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-08-28 11:50 ` Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 10/11] block: Replace nested aio_poll with bdrv_aio_poll Fam Zheng 2015-08-28 11:50 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-07-29 4:42 ` [Qemu-devel] [PATCH v2 11/11] block: Only poll block layer fds in bdrv_aio_poll Fam Zheng 2015-07-29 7:36 ` Paolo Bonzini 2015-07-29 7:37 ` Paolo Bonzini 2015-07-29 10:57 ` Fam Zheng 2015-07-29 11:02 ` Paolo Bonzini 2015-07-29 11:53 ` Fam Zheng 2015-07-29 12:03 ` Paolo Bonzini 2015-07-30 1:35 ` Fam Zheng 2015-07-30 13:22 ` Paolo Bonzini 2015-09-09 3:22 ` Fam Zheng 2015-09-11 8:15 ` Paolo Bonzini 2015-09-11 9:14 ` Fam Zheng 2015-09-11 9:36 ` [Qemu-devel] [Qemu-block] " Alberto Garcia 2015-09-11 9:43 ` Daniel P. Berrange 2015-09-11 9:44 ` Fam Zheng 2015-09-11 9:54 ` Paolo Bonzini 2015-09-11 10:40 ` Fam Zheng 2015-09-11 10:46 ` Paolo Bonzini 2015-09-11 11:01 ` Fam Zheng 2015-09-11 11:02 ` Paolo Bonzini 2015-09-11 11:12 ` Fam Zheng 2015-09-11 9:45 ` Paolo Bonzini 2015-07-29 7:38 ` [Qemu-devel] [PATCH v2 00/11] aio: Introduce handler type to fix nested aio_poll for dataplane Paolo Bonzini 2015-08-28 11:53 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi 2015-09-07 6:28 ` Fam Zheng 2015-09-11 10:39 ` [Qemu-devel] " Kevin Wolf 2015-09-11 11:46 ` Fam Zheng 2015-09-11 12:22 ` Kevin Wolf 2015-09-14 7:27 ` Fam Zheng 2015-09-14 8:40 ` Kevin Wolf 2015-09-28 9:31 ` Stefan Hajnoczi
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).