From nobody Sun Apr 13 08:39:43 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 14875836446551012.1716340675755; Mon, 20 Feb 2017 01:40:44 -0800 (PST) Received: from localhost ([::1]:36950 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfkSZ-00046a-8M for importer@patchew.org; Mon, 20 Feb 2017 04:40:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60052) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfkLt-0006wP-Ci for qemu-devel@nongnu.org; Mon, 20 Feb 2017 04:33:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfkLr-0007G6-FI for qemu-devel@nongnu.org; Mon, 20 Feb 2017 04:33:49 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45314) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cfkLq-0007Fi-MJ for qemu-devel@nongnu.org; Mon, 20 Feb 2017 04:33:47 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D35B13B755; Mon, 20 Feb 2017 09:33:46 +0000 (UTC) Received: from localhost (ovpn-116-137.ams2.redhat.com [10.36.116.137]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1K9XjZZ031538; Mon, 20 Feb 2017 04:33:46 -0500 From: Stefan Hajnoczi To: Date: Mon, 20 Feb 2017 09:32:54 +0000 Message-Id: <20170220093304.20515-15-stefanha@redhat.com> In-Reply-To: <20170220093304.20515-1-stefanha@redhat.com> References: <20170220093304.20515-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 20 Feb 2017 09:33:46 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 14/24] block: explicitly acquire aiocontext in bottom halves that need it X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Stefan Hajnoczi , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Paolo Bonzini Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Daniel P. Berrange Message-id: 20170213135235.12274-15-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi --- block/archipelago.c | 3 +++ block/blkreplay.c | 2 +- block/block-backend.c | 6 ++++++ block/curl.c | 26 ++++++++++++++++++-------- block/gluster.c | 9 +-------- block/io.c | 6 +++++- block/iscsi.c | 6 +++++- block/linux-aio.c | 15 +++++++++------ block/nfs.c | 3 ++- block/null.c | 4 ++++ block/qed.c | 3 +++ block/rbd.c | 4 ++++ dma-helpers.c | 2 ++ hw/block/virtio-blk.c | 2 ++ hw/scsi/scsi-bus.c | 2 ++ util/async.c | 4 ++-- util/thread-pool.c | 2 ++ 17 files changed, 71 insertions(+), 28 deletions(-) diff --git a/block/archipelago.c b/block/archipelago.c index 2449cfc..a624390 100644 --- a/block/archipelago.c +++ b/block/archipelago.c @@ -310,8 +310,11 @@ static void qemu_archipelago_complete_aio(void *opaque) { AIORequestData *reqdata =3D (AIORequestData *) opaque; ArchipelagoAIOCB *aio_cb =3D (ArchipelagoAIOCB *) reqdata->aio_cb; + AioContext *ctx =3D bdrv_get_aio_context(aio_cb->common.bs); =20 + aio_context_acquire(ctx); aio_cb->common.cb(aio_cb->common.opaque, aio_cb->ret); + aio_context_release(ctx); aio_cb->status =3D 0; =20 qemu_aio_unref(aio_cb); diff --git a/block/blkreplay.c b/block/blkreplay.c index a741654..cfc8c5b 100755 --- a/block/blkreplay.c +++ b/block/blkreplay.c @@ -60,7 +60,7 @@ static int64_t blkreplay_getlength(BlockDriverState *bs) static void blkreplay_bh_cb(void *opaque) { Request *req =3D opaque; - qemu_coroutine_enter(req->co); + aio_co_wake(req->co); qemu_bh_delete(req->bh); g_free(req); } diff --git a/block/block-backend.c b/block/block-backend.c index 1177598..bfc0e6b 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -939,9 +939,12 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags = flags) static void error_callback_bh(void *opaque) { struct BlockBackendAIOCB *acb =3D opaque; + AioContext *ctx =3D bdrv_get_aio_context(acb->common.bs); =20 bdrv_dec_in_flight(acb->common.bs); + aio_context_acquire(ctx); acb->common.cb(acb->common.opaque, acb->ret); + aio_context_release(ctx); qemu_aio_unref(acb); } =20 @@ -983,9 +986,12 @@ static void blk_aio_complete(BlkAioEmAIOCB *acb) static void blk_aio_complete_bh(void *opaque) { BlkAioEmAIOCB *acb =3D opaque; + AioContext *ctx =3D bdrv_get_aio_context(acb->common.bs); =20 assert(acb->has_returned); + aio_context_acquire(ctx); blk_aio_complete(acb); + aio_context_release(ctx); } =20 static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int byt= es, diff --git a/block/curl.c b/block/curl.c index 05b9ca3..f3f063b 100644 --- a/block/curl.c +++ b/block/curl.c @@ -796,13 +796,18 @@ static void curl_readv_bh_cb(void *p) { CURLState *state; int running; + int ret =3D -EINPROGRESS; =20 CURLAIOCB *acb =3D p; - BDRVCURLState *s =3D acb->common.bs->opaque; + BlockDriverState *bs =3D acb->common.bs; + BDRVCURLState *s =3D bs->opaque; + AioContext *ctx =3D bdrv_get_aio_context(bs); =20 size_t start =3D acb->sector_num * BDRV_SECTOR_SIZE; size_t end; =20 + aio_context_acquire(ctx); + // In case we have the requested data already (e.g. read-ahead), // we can just call the callback and be done. switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, ac= b)) { @@ -810,7 +815,7 @@ static void curl_readv_bh_cb(void *p) qemu_aio_unref(acb); // fall through case FIND_RET_WAIT: - return; + goto out; default: break; } @@ -818,9 +823,8 @@ static void curl_readv_bh_cb(void *p) // No cache found, so let's start a new request state =3D curl_init_state(acb->common.bs, s); if (!state) { - acb->common.cb(acb->common.opaque, -EIO); - qemu_aio_unref(acb); - return; + ret =3D -EIO; + goto out; } =20 acb->start =3D 0; @@ -834,9 +838,8 @@ static void curl_readv_bh_cb(void *p) state->orig_buf =3D g_try_malloc(state->buf_len); if (state->buf_len && state->orig_buf =3D=3D NULL) { curl_clean_state(state); - acb->common.cb(acb->common.opaque, -ENOMEM); - qemu_aio_unref(acb); - return; + ret =3D -ENOMEM; + goto out; } state->acb[0] =3D acb; =20 @@ -849,6 +852,13 @@ static void curl_readv_bh_cb(void *p) =20 /* Tell curl it needs to kick things off */ curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); + +out: + if (ret !=3D -EINPROGRESS) { + acb->common.cb(acb->common.opaque, ret); + qemu_aio_unref(acb); + } + aio_context_release(ctx); } =20 static BlockAIOCB *curl_aio_readv(BlockDriverState *bs, diff --git a/block/gluster.c b/block/gluster.c index 1a22f29..56b4abe 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -698,13 +698,6 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsG= luster *gconf, return qemu_gluster_glfs_init(gconf, errp); } =20 -static void qemu_gluster_complete_aio(void *opaque) -{ - GlusterAIOCB *acb =3D (GlusterAIOCB *)opaque; - - qemu_coroutine_enter(acb->coroutine); -} - /* * AIO callback routine called from GlusterFS thread. */ @@ -720,7 +713,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ss= ize_t ret, void *arg) acb->ret =3D -EIO; /* Partial read/write - fail it */ } =20 - aio_bh_schedule_oneshot(acb->aio_context, qemu_gluster_complete_aio, a= cb); + aio_co_schedule(acb->aio_context, acb->coroutine); } =20 static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags) diff --git a/block/io.c b/block/io.c index dd6c74f..8486e27 100644 --- a/block/io.c +++ b/block/io.c @@ -189,7 +189,7 @@ static void bdrv_co_drain_bh_cb(void *opaque) bdrv_dec_in_flight(bs); bdrv_drained_begin(bs); data->done =3D true; - qemu_coroutine_enter(co); + aio_co_wake(co); } =20 static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) @@ -2152,9 +2152,13 @@ static void bdrv_co_complete(BlockAIOCBCoroutine *ac= b) static void bdrv_co_em_bh(void *opaque) { BlockAIOCBCoroutine *acb =3D opaque; + BlockDriverState *bs =3D acb->common.bs; + AioContext *ctx =3D bdrv_get_aio_context(bs); =20 assert(!acb->need_bh); + aio_context_acquire(ctx); bdrv_co_complete(acb); + aio_context_release(ctx); } =20 static void bdrv_co_maybe_schedule_bh(BlockAIOCBCoroutine *acb) diff --git a/block/iscsi.c b/block/iscsi.c index 303b108..4fb43c2 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -136,13 +136,16 @@ static void iscsi_bh_cb(void *p) { IscsiAIOCB *acb =3D p; + AioContext *ctx =3D bdrv_get_aio_context(acb->common.bs); =20 qemu_bh_delete(acb->bh); =20 g_free(acb->buf); acb->buf =3D NULL; =20 + aio_context_acquire(ctx); acb->common.cb(acb->common.opaque, acb->status); + aio_context_release(ctx); =20 if (acb->task !=3D NULL) { scsi_free_scsi_task(acb->task); @@ -165,8 +168,9 @@ iscsi_schedule_bh(IscsiAIOCB *acb) static void iscsi_co_generic_bh_cb(void *opaque) { struct IscsiTask *iTask =3D opaque; + iTask->complete =3D 1; - qemu_coroutine_enter(iTask->co); + aio_co_wake(iTask->co); } =20 static void iscsi_retry_timer_expired(void *opaque) diff --git a/block/linux-aio.c b/block/linux-aio.c index 277c016..f7ae38a 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -54,10 +54,10 @@ struct LinuxAioState { io_context_t ctx; EventNotifier e; =20 - /* io queue for submit at batch */ + /* io queue for submit at batch. Protected by AioContext lock. */ LaioQueue io_q; =20 - /* I/O completion processing */ + /* I/O completion processing. Only runs in I/O thread. */ QEMUBH *completion_bh; int event_idx; int event_max; @@ -75,6 +75,7 @@ static inline ssize_t io_event_ret(struct io_event *ev) */ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb) { + LinuxAioState *s =3D laiocb->ctx; int ret; =20 ret =3D laiocb->ret; @@ -93,6 +94,7 @@ static void qemu_laio_process_completion(struct qemu_laio= cb *laiocb) } =20 laiocb->ret =3D ret; + aio_context_acquire(s->aio_context); if (laiocb->co) { /* If the coroutine is already entered it must be in ioq_submit() = and * will notice laio->ret has been filled in when it eventually runs @@ -106,6 +108,7 @@ static void qemu_laio_process_completion(struct qemu_la= iocb *laiocb) laiocb->common.cb(laiocb->common.opaque, ret); qemu_aio_unref(laiocb); } + aio_context_release(s->aio_context); } =20 /** @@ -234,9 +237,12 @@ static void qemu_laio_process_completions(LinuxAioStat= e *s) static void qemu_laio_process_completions_and_submit(LinuxAioState *s) { qemu_laio_process_completions(s); + + aio_context_acquire(s->aio_context); if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { ioq_submit(s); } + aio_context_release(s->aio_context); } =20 static void qemu_laio_completion_bh(void *opaque) @@ -251,9 +257,7 @@ static void qemu_laio_completion_cb(EventNotifier *e) LinuxAioState *s =3D container_of(e, LinuxAioState, e); =20 if (event_notifier_test_and_clear(&s->e)) { - aio_context_acquire(s->aio_context); qemu_laio_process_completions_and_submit(s); - aio_context_release(s->aio_context); } } =20 @@ -267,9 +271,7 @@ static bool qemu_laio_poll_cb(void *opaque) return false; } =20 - aio_context_acquire(s->aio_context); qemu_laio_process_completions_and_submit(s); - aio_context_release(s->aio_context); return true; } =20 @@ -459,6 +461,7 @@ void laio_detach_aio_context(LinuxAioState *s, AioConte= xt *old_context) { aio_set_event_notifier(old_context, &s->e, false, NULL, NULL); qemu_bh_delete(s->completion_bh); + s->aio_context =3D NULL; } =20 void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context) diff --git a/block/nfs.c b/block/nfs.c index 5ce968c..08b43dd 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -237,8 +237,9 @@ static void nfs_co_init_task(BlockDriverState *bs, NFSR= PC *task) static void nfs_co_generic_bh_cb(void *opaque) { NFSRPC *task =3D opaque; + task->complete =3D 1; - qemu_coroutine_enter(task->co); + aio_co_wake(task->co); } =20 static void diff --git a/block/null.c b/block/null.c index 356209a..5eb2038 100644 --- a/block/null.c +++ b/block/null.c @@ -134,7 +134,11 @@ static const AIOCBInfo null_aiocb_info =3D { static void null_bh_cb(void *opaque) { NullAIOCB *acb =3D opaque; + AioContext *ctx =3D bdrv_get_aio_context(acb->common.bs); + + aio_context_acquire(ctx); acb->common.cb(acb->common.opaque, 0); + aio_context_release(ctx); qemu_aio_unref(acb); } =20 diff --git a/block/qed.c b/block/qed.c index a21d025..db8295d 100644 --- a/block/qed.c +++ b/block/qed.c @@ -942,6 +942,7 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTab= le *table, int index, static void qed_aio_complete_bh(void *opaque) { QEDAIOCB *acb =3D opaque; + BDRVQEDState *s =3D acb_to_s(acb); BlockCompletionFunc *cb =3D acb->common.cb; void *user_opaque =3D acb->common.opaque; int ret =3D acb->bh_ret; @@ -949,7 +950,9 @@ static void qed_aio_complete_bh(void *opaque) qemu_aio_unref(acb); =20 /* Invoke callback */ + qed_acquire(s); cb(user_opaque, ret); + qed_release(s); } =20 static void qed_aio_complete(QEDAIOCB *acb, int ret) diff --git a/block/rbd.c b/block/rbd.c index a57b3e3..2cb2cb4 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -413,6 +413,7 @@ shutdown: static void qemu_rbd_complete_aio(RADOSCB *rcb) { RBDAIOCB *acb =3D rcb->acb; + AioContext *ctx =3D bdrv_get_aio_context(acb->common.bs); int64_t r; =20 r =3D rcb->ret; @@ -445,7 +446,10 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb) qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size); } qemu_vfree(acb->bounce); + + aio_context_acquire(ctx); acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret)); + aio_context_release(ctx); =20 qemu_aio_unref(acb); } diff --git a/dma-helpers.c b/dma-helpers.c index 97157cc..2d7e02d 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -166,8 +166,10 @@ static void dma_blk_cb(void *opaque, int ret) QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align)= ); } =20 + aio_context_acquire(dbs->ctx); dbs->acb =3D dbs->io_func(dbs->offset, &dbs->iov, dma_blk_cb, dbs, dbs->io_func_opaque); + aio_context_release(dbs->ctx); assert(dbs->acb); } =20 diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index a00ee38..af652f3 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -639,6 +639,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) =20 s->rq =3D NULL; =20 + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); while (req) { VirtIOBlockReq *next =3D req->next; if (virtio_blk_handle_request(req, &mrb)) { @@ -659,6 +660,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) if (mrb.num_reqs) { virtio_blk_submit_multireq(s->blk, &mrb); } + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); } =20 static void virtio_blk_dma_restart_cb(void *opaque, int running, diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 5940cb1..c9f0ac0 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -105,6 +105,7 @@ static void scsi_dma_restart_bh(void *opaque) qemu_bh_delete(s->bh); s->bh =3D NULL; =20 + aio_context_acquire(blk_get_aio_context(s->conf.blk)); QTAILQ_FOREACH_SAFE(req, &s->requests, next, next) { scsi_req_ref(req); if (req->retry) { @@ -122,6 +123,7 @@ static void scsi_dma_restart_bh(void *opaque) } scsi_req_unref(req); } + aio_context_release(blk_get_aio_context(s->conf.blk)); } =20 void scsi_req_retry(SCSIRequest *req) diff --git a/util/async.c b/util/async.c index aec8016..c54da71 100644 --- a/util/async.c +++ b/util/async.c @@ -114,9 +114,7 @@ int aio_bh_poll(AioContext *ctx) ret =3D 1; } bh->idle =3D 0; - aio_context_acquire(ctx); aio_bh_call(bh); - aio_context_release(ctx); } if (bh->deleted) { deleted =3D true; @@ -389,7 +387,9 @@ static void co_schedule_bh_cb(void *opaque) Coroutine *co =3D QSLIST_FIRST(&straight); QSLIST_REMOVE_HEAD(&straight, co_scheduled_next); trace_aio_co_schedule_bh_cb(ctx, co); + aio_context_acquire(ctx); qemu_coroutine_enter(co); + aio_context_release(ctx); } } =20 diff --git a/util/thread-pool.c b/util/thread-pool.c index 6fba913..7c9cec5 100644 --- a/util/thread-pool.c +++ b/util/thread-pool.c @@ -165,6 +165,7 @@ static void thread_pool_completion_bh(void *opaque) ThreadPool *pool =3D opaque; ThreadPoolElement *elem, *next; =20 + aio_context_acquire(pool->ctx); restart: QLIST_FOREACH_SAFE(elem, &pool->head, all, next) { if (elem->state !=3D THREAD_DONE) { @@ -191,6 +192,7 @@ restart: qemu_aio_unref(elem); } } + aio_context_release(pool->ctx); } =20 static void thread_pool_cancel(BlockAIOCB *acb) --=20 2.9.3