* [Qemu-devel] [PATCH 0/2] block: introduce and use aio_bh_schedule_oneshot @ 2016-10-03 16:14 Paolo Bonzini 2016-10-03 16:14 ` [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot Paolo Bonzini ` (2 more replies) 0 siblings, 3 replies; 10+ messages in thread From: Paolo Bonzini @ 2016-10-03 16:14 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, famz, stefanha This simplifies a bit using the bottom half API in the common case of one-shot bottom halves, that are created once per usage. This patch comes from the multiqueue series. Paolo Paolo Bonzini (2): async: add aio_bh_schedule_oneshot block: use aio_bh_schedule_oneshot async.c | 27 +++++++++++++++++++++++---- block/archipelago.c | 5 +---- block/blkdebug.c | 7 +------ block/blkverify.c | 8 ++------ block/block-backend.c | 23 +++++++---------------- block/curl.c | 7 +------ block/gluster.c | 6 +----- block/io.c | 11 +++-------- block/iscsi.c | 7 ++----- block/nfs.c | 7 ++----- block/null.c | 5 +---- block/qed.c | 6 ++---- block/qed.h | 1 - block/rbd.c | 8 ++------ blockjob.c | 7 ++----- include/block/aio.h | 10 ++++++++++ 16 files changed, 60 insertions(+), 85 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot 2016-10-03 16:14 [Qemu-devel] [PATCH 0/2] block: introduce and use aio_bh_schedule_oneshot Paolo Bonzini @ 2016-10-03 16:14 ` Paolo Bonzini 2016-10-05 13:13 ` Stefan Hajnoczi 2016-10-03 16:14 ` [Qemu-devel] [PATCH 2/2] block: use aio_bh_schedule_oneshot Paolo Bonzini 2016-10-05 11:08 ` [Qemu-devel] [PATCH 0/2] block: introduce and " Kevin Wolf 2 siblings, 1 reply; 10+ messages in thread From: Paolo Bonzini @ 2016-10-03 16:14 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, famz, stefanha qemu_bh_delete is already clearing bh->scheduled at the same time as it's setting bh->deleted. Since it's not using any memory barriers, there is no synchronization going on for bh->deleted, and this makes the bh->deleted checks superfluous in aio_compute_timeout, aio_bh_poll and aio_ctx_check. Just remove them, and put the (bh->scheduled && bh->deleted) combo to work in a new function aio_bh_schedule_oneshot. The new function removes the need to save the QEMUBH pointer between the creation and the execution of the bottom half. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- async.c | 27 +++++++++++++++++++++++---- include/block/aio.h | 10 ++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/async.c b/async.c index 3bca9b0..f30d011 100644 --- a/async.c +++ b/async.c @@ -44,6 +44,25 @@ struct QEMUBH { bool deleted; }; +void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque) +{ + QEMUBH *bh; + bh = g_new(QEMUBH, 1); + *bh = (QEMUBH){ + .ctx = ctx, + .cb = cb, + .opaque = opaque, + }; + qemu_mutex_lock(&ctx->bh_lock); + bh->next = ctx->first_bh; + bh->scheduled = 1; + bh->deleted = 1; + /* Make sure that the members are ready before putting bh into list */ + smp_wmb(); + ctx->first_bh = bh; + qemu_mutex_unlock(&ctx->bh_lock); +} + QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) { QEMUBH *bh; @@ -86,7 +105,7 @@ int aio_bh_poll(AioContext *ctx) * thread sees the zero before bh->cb has run, and thus will call * aio_notify again if necessary. */ - if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) { + if (atomic_xchg(&bh->scheduled, 0)) { /* Idle BHs and the notify BH don't count as progress */ if (!bh->idle && bh != ctx->notify_dummy_bh) { ret = 1; @@ -104,7 +123,7 @@ int aio_bh_poll(AioContext *ctx) bhp = &ctx->first_bh; while (*bhp) { bh = *bhp; - if (bh->deleted) { + if (bh->deleted && !bh->scheduled) { *bhp = bh->next; g_free(bh); } else { @@ -168,7 +187,7 @@ aio_compute_timeout(AioContext *ctx) QEMUBH *bh; for (bh = ctx->first_bh; bh; bh = bh->next) { - if (!bh->deleted && bh->scheduled) { + if (bh->scheduled) { if (bh->idle) { /* idle bottom halves will be polled at least * every 10ms */ @@ -216,7 +235,7 @@ aio_ctx_check(GSource *source) aio_notify_accept(ctx); for (bh = ctx->first_bh; bh; bh = bh->next) { - if (!bh->deleted && bh->scheduled) { + if (bh->scheduled) { return true; } } diff --git a/include/block/aio.h b/include/block/aio.h index 173c1ed..be7dd3b 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -181,6 +181,16 @@ void aio_context_acquire(AioContext *ctx); void aio_context_release(AioContext *ctx); /** + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run + * only once and as soon as possible. + * + * Bottom halves are lightweight callbacks whose invocation is guaranteed + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure + * is opaque and must be allocated prior to its use. + */ +void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); + +/** * aio_bh_new: Allocate a new bottom half structure. * * Bottom halves are lightweight callbacks whose invocation is guaranteed -- 2.7.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot 2016-10-03 16:14 ` [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot Paolo Bonzini @ 2016-10-05 13:13 ` Stefan Hajnoczi 2016-10-05 13:55 ` Paolo Bonzini 0 siblings, 1 reply; 10+ messages in thread From: Stefan Hajnoczi @ 2016-10-05 13:13 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel, kwolf, famz [-- Attachment #1: Type: text/plain, Size: 4407 bytes --] On Mon, Oct 03, 2016 at 06:14:15PM +0200, Paolo Bonzini wrote: > qemu_bh_delete is already clearing bh->scheduled at the same time > as it's setting bh->deleted. Since it's not using any memory > barriers, there is no synchronization going on for bh->deleted, > and this makes the bh->deleted checks superfluous in aio_compute_timeout, > aio_bh_poll and aio_ctx_check. Yikes. On one hand this sounds scary but in practice qemu_bh_delete() isn't called from another thread so the next aio_bh_poll() will indeed clean it up instead of dispatching a deleted BH. Due to the nature of this change I suggest making it in a separate patch. > Just remove them, and put the (bh->scheduled && bh->deleted) combo > to work in a new function aio_bh_schedule_oneshot. The new function > removes the need to save the QEMUBH pointer between the creation > and the execution of the bottom half. > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > async.c | 27 +++++++++++++++++++++++---- > include/block/aio.h | 10 ++++++++++ > 2 files changed, 33 insertions(+), 4 deletions(-) > > diff --git a/async.c b/async.c > index 3bca9b0..f30d011 100644 > --- a/async.c > +++ b/async.c > @@ -44,6 +44,25 @@ struct QEMUBH { > bool deleted; > }; > > +void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque) > +{ > + QEMUBH *bh; > + bh = g_new(QEMUBH, 1); > + *bh = (QEMUBH){ > + .ctx = ctx, > + .cb = cb, > + .opaque = opaque, > + }; > + qemu_mutex_lock(&ctx->bh_lock); > + bh->next = ctx->first_bh; > + bh->scheduled = 1; > + bh->deleted = 1; > + /* Make sure that the members are ready before putting bh into list */ > + smp_wmb(); > + ctx->first_bh = bh; > + qemu_mutex_unlock(&ctx->bh_lock); > +} > + > QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) > { > QEMUBH *bh; > @@ -86,7 +105,7 @@ int aio_bh_poll(AioContext *ctx) > * thread sees the zero before bh->cb has run, and thus will call > * aio_notify again if necessary. > */ > - if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) { > + if (atomic_xchg(&bh->scheduled, 0)) { > /* Idle BHs and the notify BH don't count as progress */ > if (!bh->idle && bh != ctx->notify_dummy_bh) { > ret = 1; > @@ -104,7 +123,7 @@ int aio_bh_poll(AioContext *ctx) > bhp = &ctx->first_bh; > while (*bhp) { > bh = *bhp; > - if (bh->deleted) { > + if (bh->deleted && !bh->scheduled) { > *bhp = bh->next; > g_free(bh); > } else { > @@ -168,7 +187,7 @@ aio_compute_timeout(AioContext *ctx) > QEMUBH *bh; > > for (bh = ctx->first_bh; bh; bh = bh->next) { > - if (!bh->deleted && bh->scheduled) { > + if (bh->scheduled) { > if (bh->idle) { > /* idle bottom halves will be polled at least > * every 10ms */ > @@ -216,7 +235,7 @@ aio_ctx_check(GSource *source) > aio_notify_accept(ctx); > > for (bh = ctx->first_bh; bh; bh = bh->next) { > - if (!bh->deleted && bh->scheduled) { > + if (bh->scheduled) { > return true; > } > } > diff --git a/include/block/aio.h b/include/block/aio.h > index 173c1ed..be7dd3b 100644 > --- a/include/block/aio.h > +++ b/include/block/aio.h > @@ -181,6 +181,16 @@ void aio_context_acquire(AioContext *ctx); > void aio_context_release(AioContext *ctx); > > /** > + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run > + * only once and as soon as possible. > + * > + * Bottom halves are lightweight callbacks whose invocation is guaranteed > + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure > + * is opaque and must be allocated prior to its use. I'm confused. There is no QEMUBH structure in this function prototype. Is this comment from an earlier version of this function? > + */ > +void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); > + > +/** > * aio_bh_new: Allocate a new bottom half structure. > * > * Bottom halves are lightweight callbacks whose invocation is guaranteed > -- > 2.7.4 > > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 455 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot 2016-10-05 13:13 ` Stefan Hajnoczi @ 2016-10-05 13:55 ` Paolo Bonzini 2016-10-05 14:20 ` Kevin Wolf 0 siblings, 1 reply; 10+ messages in thread From: Paolo Bonzini @ 2016-10-05 13:55 UTC (permalink / raw) To: Stefan Hajnoczi; +Cc: qemu-devel, kwolf, famz On 05/10/2016 15:13, Stefan Hajnoczi wrote: > > qemu_bh_delete is already clearing bh->scheduled at the same time > > as it's setting bh->deleted. Since it's not using any memory > > barriers, there is no synchronization going on for bh->deleted, > > and this makes the bh->deleted checks superfluous in aio_compute_timeout, > > aio_bh_poll and aio_ctx_check. > > Yikes. On one hand this sounds scary but in practice qemu_bh_delete() > isn't called from another thread so the next aio_bh_poll() will indeed > clean it up instead of dispatching a deleted BH. > > Due to the nature of this change I suggest making it in a separate > patch. Separate from what? (Sorry if I'm being dense). >> >> + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run >> + * only once and as soon as possible. >> + * >> + * Bottom halves are lightweight callbacks whose invocation is guaranteed >> + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure >> + * is opaque and must be allocated prior to its use. > > I'm confused. There is no QEMUBH structure in this function > prototype. Is this comment from an earlier version of this function? No, it's from aio_bh_new. Of course this one is neither wait-free nor signal-safe. Kevin, do you want me to respin? Paolo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot 2016-10-05 13:55 ` Paolo Bonzini @ 2016-10-05 14:20 ` Kevin Wolf 2016-10-05 14:25 ` Paolo Bonzini 0 siblings, 1 reply; 10+ messages in thread From: Kevin Wolf @ 2016-10-05 14:20 UTC (permalink / raw) To: Paolo Bonzini; +Cc: Stefan Hajnoczi, qemu-devel, famz Am 05.10.2016 um 15:55 hat Paolo Bonzini geschrieben: > On 05/10/2016 15:13, Stefan Hajnoczi wrote: > > > qemu_bh_delete is already clearing bh->scheduled at the same time > > > as it's setting bh->deleted. Since it's not using any memory > > > barriers, there is no synchronization going on for bh->deleted, > > > and this makes the bh->deleted checks superfluous in aio_compute_timeout, > > > aio_bh_poll and aio_ctx_check. > > > > Yikes. On one hand this sounds scary but in practice qemu_bh_delete() > > isn't called from another thread so the next aio_bh_poll() will indeed > > clean it up instead of dispatching a deleted BH. > > > > Due to the nature of this change I suggest making it in a separate > > patch. > > Separate from what? (Sorry if I'm being dense). > > >> > >> + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run > >> + * only once and as soon as possible. > >> + * > >> + * Bottom halves are lightweight callbacks whose invocation is guaranteed > >> + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure > >> + * is opaque and must be allocated prior to its use. > > > > I'm confused. There is no QEMUBH structure in this function > > prototype. Is this comment from an earlier version of this function? > > No, it's from aio_bh_new. Of course this one is neither wait-free nor > signal-safe. Kevin, do you want me to respin? If the comment is wrong, either post a v2 of this patch or just reply with a new version of the comment and I'll squash it in. Your choice, I don't mind either way. Kevin ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot 2016-10-05 14:20 ` Kevin Wolf @ 2016-10-05 14:25 ` Paolo Bonzini 2016-10-05 15:26 ` Kevin Wolf 0 siblings, 1 reply; 10+ messages in thread From: Paolo Bonzini @ 2016-10-05 14:25 UTC (permalink / raw) To: Kevin Wolf; +Cc: Stefan Hajnoczi, qemu-devel, famz On 05/10/2016 16:20, Kevin Wolf wrote: > Am 05.10.2016 um 15:55 hat Paolo Bonzini geschrieben: >> On 05/10/2016 15:13, Stefan Hajnoczi wrote: >>>> qemu_bh_delete is already clearing bh->scheduled at the same time >>>> as it's setting bh->deleted. Since it's not using any memory >>>> barriers, there is no synchronization going on for bh->deleted, >>>> and this makes the bh->deleted checks superfluous in aio_compute_timeout, >>>> aio_bh_poll and aio_ctx_check. >>> >>> Yikes. On one hand this sounds scary but in practice qemu_bh_delete() >>> isn't called from another thread so the next aio_bh_poll() will indeed >>> clean it up instead of dispatching a deleted BH. >>> >>> Due to the nature of this change I suggest making it in a separate >>> patch. >> >> Separate from what? (Sorry if I'm being dense). >> >>>> >>>> + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run >>>> + * only once and as soon as possible. >>>> + * >>>> + * Bottom halves are lightweight callbacks whose invocation is guaranteed >>>> + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure >>>> + * is opaque and must be allocated prior to its use. >>> >>> I'm confused. There is no QEMUBH structure in this function >>> prototype. Is this comment from an earlier version of this function? >> >> No, it's from aio_bh_new. Of course this one is neither wait-free nor >> signal-safe. Kevin, do you want me to respin? > > If the comment is wrong, either post a v2 of this patch or just reply > with a new version of the comment and I'll squash it in. Your choice, I > don't mind either way. Just removing those three lines would be okay. Paolo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot 2016-10-05 14:25 ` Paolo Bonzini @ 2016-10-05 15:26 ` Kevin Wolf 0 siblings, 0 replies; 10+ messages in thread From: Kevin Wolf @ 2016-10-05 15:26 UTC (permalink / raw) To: Paolo Bonzini; +Cc: Stefan Hajnoczi, qemu-devel, famz Am 05.10.2016 um 16:25 hat Paolo Bonzini geschrieben: > > > On 05/10/2016 16:20, Kevin Wolf wrote: > > Am 05.10.2016 um 15:55 hat Paolo Bonzini geschrieben: > >> On 05/10/2016 15:13, Stefan Hajnoczi wrote: > >>>> qemu_bh_delete is already clearing bh->scheduled at the same time > >>>> as it's setting bh->deleted. Since it's not using any memory > >>>> barriers, there is no synchronization going on for bh->deleted, > >>>> and this makes the bh->deleted checks superfluous in aio_compute_timeout, > >>>> aio_bh_poll and aio_ctx_check. > >>> > >>> Yikes. On one hand this sounds scary but in practice qemu_bh_delete() > >>> isn't called from another thread so the next aio_bh_poll() will indeed > >>> clean it up instead of dispatching a deleted BH. > >>> > >>> Due to the nature of this change I suggest making it in a separate > >>> patch. > >> > >> Separate from what? (Sorry if I'm being dense). > >> > >>>> > >>>> + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run > >>>> + * only once and as soon as possible. > >>>> + * > >>>> + * Bottom halves are lightweight callbacks whose invocation is guaranteed > >>>> + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure > >>>> + * is opaque and must be allocated prior to its use. > >>> > >>> I'm confused. There is no QEMUBH structure in this function > >>> prototype. Is this comment from an earlier version of this function? > >> > >> No, it's from aio_bh_new. Of course this one is neither wait-free nor > >> signal-safe. Kevin, do you want me to respin? > > > > If the comment is wrong, either post a v2 of this patch or just reply > > with a new version of the comment and I'll squash it in. Your choice, I > > don't mind either way. > > Just removing those three lines would be okay. Ok, done. Kevin ^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/2] block: use aio_bh_schedule_oneshot 2016-10-03 16:14 [Qemu-devel] [PATCH 0/2] block: introduce and use aio_bh_schedule_oneshot Paolo Bonzini 2016-10-03 16:14 ` [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot Paolo Bonzini @ 2016-10-03 16:14 ` Paolo Bonzini 2016-10-05 13:16 ` Stefan Hajnoczi 2016-10-05 11:08 ` [Qemu-devel] [PATCH 0/2] block: introduce and " Kevin Wolf 2 siblings, 1 reply; 10+ messages in thread From: Paolo Bonzini @ 2016-10-03 16:14 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, famz, stefanha This simplifies bottom half handlers by removing calls to qemu_bh_delete and thus removing the need to stash the bottom half pointer in the opaque datum. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- block/archipelago.c | 5 +---- block/blkdebug.c | 7 +------ block/blkverify.c | 8 ++------ block/block-backend.c | 23 +++++++---------------- block/curl.c | 7 +------ block/gluster.c | 6 +----- block/io.c | 11 +++-------- block/iscsi.c | 7 ++----- block/nfs.c | 7 ++----- block/null.c | 5 +---- block/qed.c | 6 ++---- block/qed.h | 1 - block/rbd.c | 8 ++------ blockjob.c | 7 ++----- 14 files changed, 27 insertions(+), 81 deletions(-) diff --git a/block/archipelago.c b/block/archipelago.c index 37b8aca..2449cfc 100644 --- a/block/archipelago.c +++ b/block/archipelago.c @@ -87,7 +87,6 @@ typedef enum { typedef struct ArchipelagoAIOCB { BlockAIOCB common; - QEMUBH *bh; struct BDRVArchipelagoState *s; QEMUIOVector *qiov; ARCHIPCmd cmd; @@ -154,11 +153,10 @@ static void archipelago_finish_aiocb(AIORequestData *reqdata) } else if (reqdata->aio_cb->ret == reqdata->segreq->total) { reqdata->aio_cb->ret = 0; } - reqdata->aio_cb->bh = aio_bh_new( + aio_bh_schedule_oneshot( bdrv_get_aio_context(reqdata->aio_cb->common.bs), qemu_archipelago_complete_aio, reqdata ); - qemu_bh_schedule(reqdata->aio_cb->bh); } static int wait_reply(struct xseg *xseg, xport srcport, struct xseg_port *port, @@ -313,7 +311,6 @@ static void qemu_archipelago_complete_aio(void *opaque) AIORequestData *reqdata = (AIORequestData *) opaque; ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) reqdata->aio_cb; - qemu_bh_delete(aio_cb->bh); aio_cb->common.cb(aio_cb->common.opaque, aio_cb->ret); aio_cb->status = 0; diff --git a/block/blkdebug.c b/block/blkdebug.c index d5db166..4127571 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -49,7 +49,6 @@ typedef struct BDRVBlkdebugState { typedef struct BlkdebugAIOCB { BlockAIOCB common; - QEMUBH *bh; int ret; } BlkdebugAIOCB; @@ -410,7 +409,6 @@ out: static void error_callback_bh(void *opaque) { struct BlkdebugAIOCB *acb = opaque; - qemu_bh_delete(acb->bh); acb->common.cb(acb->common.opaque, acb->ret); qemu_aio_unref(acb); } @@ -421,7 +419,6 @@ static BlockAIOCB *inject_error(BlockDriverState *bs, BDRVBlkdebugState *s = bs->opaque; int error = rule->options.inject.error; struct BlkdebugAIOCB *acb; - QEMUBH *bh; bool immediately = rule->options.inject.immediately; if (rule->options.inject.once) { @@ -436,9 +433,7 @@ static BlockAIOCB *inject_error(BlockDriverState *bs, acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque); acb->ret = -error; - bh = aio_bh_new(bdrv_get_aio_context(bs), error_callback_bh, acb); - acb->bh = bh; - qemu_bh_schedule(bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), error_callback_bh, acb); return &acb->common; } diff --git a/block/blkverify.c b/block/blkverify.c index da62d75..28f9af6 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -22,7 +22,6 @@ typedef struct { typedef struct BlkverifyAIOCB BlkverifyAIOCB; struct BlkverifyAIOCB { BlockAIOCB common; - QEMUBH *bh; /* Request metadata */ bool is_write; @@ -175,7 +174,6 @@ static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write, { BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque); - acb->bh = NULL; acb->is_write = is_write; acb->sector_num = sector_num; acb->nb_sectors = nb_sectors; @@ -191,7 +189,6 @@ static void blkverify_aio_bh(void *opaque) { BlkverifyAIOCB *acb = opaque; - qemu_bh_delete(acb->bh); if (acb->buf) { qemu_iovec_destroy(&acb->raw_qiov); qemu_vfree(acb->buf); @@ -218,9 +215,8 @@ static void blkverify_aio_cb(void *opaque, int ret) acb->verify(acb); } - acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs), - blkverify_aio_bh, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs), + blkverify_aio_bh, acb); break; } } diff --git a/block/block-backend.c b/block/block-backend.c index 0bd19ab..37595d2 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -65,7 +65,6 @@ struct BlockBackend { typedef struct BlockBackendAIOCB { BlockAIOCB common; - QEMUBH *bh; BlockBackend *blk; int ret; } BlockBackendAIOCB; @@ -898,7 +897,6 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags) static void error_callback_bh(void *opaque) { struct BlockBackendAIOCB *acb = opaque; - qemu_bh_delete(acb->bh); acb->common.cb(acb->common.opaque, acb->ret); qemu_aio_unref(acb); } @@ -908,16 +906,12 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk, void *opaque, int ret) { struct BlockBackendAIOCB *acb; - QEMUBH *bh; acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque); acb->blk = blk; acb->ret = ret; - bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb); - acb->bh = bh; - qemu_bh_schedule(bh); - + aio_bh_schedule_oneshot(blk_get_aio_context(blk), error_callback_bh, acb); return &acb->common; } @@ -926,7 +920,6 @@ typedef struct BlkAioEmAIOCB { BlkRwCo rwco; int bytes; bool has_returned; - QEMUBH* bh; } BlkAioEmAIOCB; static const AIOCBInfo blk_aio_em_aiocb_info = { @@ -935,10 +928,6 @@ static const AIOCBInfo blk_aio_em_aiocb_info = { static void blk_aio_complete(BlkAioEmAIOCB *acb) { - if (acb->bh) { - assert(acb->has_returned); - qemu_bh_delete(acb->bh); - } if (acb->has_returned) { acb->common.cb(acb->common.opaque, acb->rwco.ret); qemu_aio_unref(acb); @@ -947,7 +936,10 @@ static void blk_aio_complete(BlkAioEmAIOCB *acb) static void blk_aio_complete_bh(void *opaque) { - blk_aio_complete(opaque); + BlkAioEmAIOCB *acb = opaque; + + assert(acb->has_returned); + blk_aio_complete(acb); } static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes, @@ -967,7 +959,6 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes, .ret = NOT_DONE, }; acb->bytes = bytes; - acb->bh = NULL; acb->has_returned = false; co = qemu_coroutine_create(co_entry, acb); @@ -975,8 +966,8 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes, acb->has_returned = true; if (acb->rwco.ret != NOT_DONE) { - acb->bh = aio_bh_new(blk_get_aio_context(blk), blk_aio_complete_bh, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(blk_get_aio_context(blk), + blk_aio_complete_bh, acb); } return &acb->common; diff --git a/block/curl.c b/block/curl.c index 571f24c..e5eaa7b 100644 --- a/block/curl.c +++ b/block/curl.c @@ -96,7 +96,6 @@ struct BDRVCURLState; typedef struct CURLAIOCB { BlockAIOCB common; - QEMUBH *bh; QEMUIOVector *qiov; int64_t sector_num; @@ -739,9 +738,6 @@ static void curl_readv_bh_cb(void *p) CURLAIOCB *acb = p; BDRVCURLState *s = acb->common.bs->opaque; - qemu_bh_delete(acb->bh); - acb->bh = NULL; - size_t start = acb->sector_num * SECTOR_SIZE; size_t end; @@ -805,8 +801,7 @@ static BlockAIOCB *curl_aio_readv(BlockDriverState *bs, acb->sector_num = sector_num; acb->nb_sectors = nb_sectors; - acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb); return &acb->common; } diff --git a/block/gluster.c b/block/gluster.c index e7bd13c..af76d7d5 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -38,7 +38,6 @@ typedef struct GlusterAIOCB { int64_t size; int ret; - QEMUBH *bh; Coroutine *coroutine; AioContext *aio_context; } GlusterAIOCB; @@ -622,8 +621,6 @@ static void qemu_gluster_complete_aio(void *opaque) { GlusterAIOCB *acb = (GlusterAIOCB *)opaque; - qemu_bh_delete(acb->bh); - acb->bh = NULL; qemu_coroutine_enter(acb->coroutine); } @@ -642,8 +639,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) acb->ret = -EIO; /* Partial read/write - fail it */ } - acb->bh = aio_bh_new(acb->aio_context, qemu_gluster_complete_aio, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(acb->aio_context, qemu_gluster_complete_aio, acb); } static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags) diff --git a/block/io.c b/block/io.c index fdf7080..c0a5410 100644 --- a/block/io.c +++ b/block/io.c @@ -171,7 +171,6 @@ static void bdrv_drain_recurse(BlockDriverState *bs) typedef struct { Coroutine *co; BlockDriverState *bs; - QEMUBH *bh; bool done; } BdrvCoDrainData; @@ -191,7 +190,6 @@ static void bdrv_co_drain_bh_cb(void *opaque) BdrvCoDrainData *data = opaque; Coroutine *co = data->co; - qemu_bh_delete(data->bh); bdrv_drain_poll(data->bs); data->done = true; qemu_coroutine_enter(co); @@ -210,9 +208,9 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) .co = qemu_coroutine_self(), .bs = bs, .done = false, - .bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_drain_bh_cb, &data), }; - qemu_bh_schedule(data.bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), + bdrv_co_drain_bh_cb, &data); qemu_coroutine_yield(); /* If we are resumed from some other event (such as an aio completion or a @@ -2070,7 +2068,6 @@ typedef struct BlockAIOCBCoroutine { bool is_write; bool need_bh; bool *done; - QEMUBH* bh; } BlockAIOCBCoroutine; static const AIOCBInfo bdrv_em_co_aiocb_info = { @@ -2090,7 +2087,6 @@ static void bdrv_co_em_bh(void *opaque) BlockAIOCBCoroutine *acb = opaque; assert(!acb->need_bh); - qemu_bh_delete(acb->bh); bdrv_co_complete(acb); } @@ -2100,8 +2096,7 @@ static void bdrv_co_maybe_schedule_bh(BlockAIOCBCoroutine *acb) if (acb->req.error != -EINPROGRESS) { BlockDriverState *bs = acb->common.bs; - acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb); } } diff --git a/block/iscsi.c b/block/iscsi.c index dff548a..46ddc35 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -95,7 +95,6 @@ typedef struct IscsiTask { int do_retry; struct scsi_task *task; Coroutine *co; - QEMUBH *bh; IscsiLun *iscsilun; QEMUTimer retry_timer; int err_code; @@ -167,7 +166,6 @@ static void iscsi_co_generic_bh_cb(void *opaque) { struct IscsiTask *iTask = opaque; iTask->complete = 1; - qemu_bh_delete(iTask->bh); qemu_coroutine_enter(iTask->co); } @@ -299,9 +297,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, out: if (iTask->co) { - iTask->bh = aio_bh_new(iTask->iscsilun->aio_context, - iscsi_co_generic_bh_cb, iTask); - qemu_bh_schedule(iTask->bh); + aio_bh_schedule_oneshot(iTask->iscsilun->aio_context, + iscsi_co_generic_bh_cb, iTask); } else { iTask->complete = 1; } diff --git a/block/nfs.c b/block/nfs.c index 8602a44..c3db2ec 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -57,7 +57,6 @@ typedef struct NFSRPC { QEMUIOVector *iov; struct stat *st; Coroutine *co; - QEMUBH *bh; NFSClient *client; } NFSRPC; @@ -103,7 +102,6 @@ static void nfs_co_generic_bh_cb(void *opaque) { NFSRPC *task = opaque; task->complete = 1; - qemu_bh_delete(task->bh); qemu_coroutine_enter(task->co); } @@ -127,9 +125,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data, error_report("NFS Error: %s", nfs_get_error(nfs)); } if (task->co) { - task->bh = aio_bh_new(task->client->aio_context, - nfs_co_generic_bh_cb, task); - qemu_bh_schedule(task->bh); + aio_bh_schedule_oneshot(task->client->aio_context, + nfs_co_generic_bh_cb, task); } else { task->complete = 1; } diff --git a/block/null.c b/block/null.c index b511010..b300390 100644 --- a/block/null.c +++ b/block/null.c @@ -124,7 +124,6 @@ static coroutine_fn int null_co_flush(BlockDriverState *bs) typedef struct { BlockAIOCB common; - QEMUBH *bh; QEMUTimer timer; } NullAIOCB; @@ -136,7 +135,6 @@ static void null_bh_cb(void *opaque) { NullAIOCB *acb = opaque; acb->common.cb(acb->common.opaque, 0); - qemu_bh_delete(acb->bh); qemu_aio_unref(acb); } @@ -164,8 +162,7 @@ static inline BlockAIOCB *null_aio_common(BlockDriverState *bs, timer_mod_ns(&acb->timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns); } else { - acb->bh = aio_bh_new(bdrv_get_aio_context(bs), null_bh_cb, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), null_bh_cb, acb); } return &acb->common; } diff --git a/block/qed.c b/block/qed.c index 426f3cb..3ee879b 100644 --- a/block/qed.c +++ b/block/qed.c @@ -909,7 +909,6 @@ static void qed_aio_complete_bh(void *opaque) void *user_opaque = acb->common.opaque; int ret = acb->bh_ret; - qemu_bh_delete(acb->bh); qemu_aio_unref(acb); /* Invoke callback */ @@ -934,9 +933,8 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret) /* Arrange for a bh to invoke the completion function */ acb->bh_ret = ret; - acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs), - qed_aio_complete_bh, acb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs), + qed_aio_complete_bh, acb); /* Start next allocating write request waiting behind this one. Note that * requests enqueue themselves when they first hit an unallocated cluster diff --git a/block/qed.h b/block/qed.h index 22b3198..9676ab9 100644 --- a/block/qed.h +++ b/block/qed.h @@ -130,7 +130,6 @@ enum { typedef struct QEDAIOCB { BlockAIOCB common; - QEMUBH *bh; int bh_ret; /* final return status for completion bh */ QSIMPLEQ_ENTRY(QEDAIOCB) next; /* next request */ int flags; /* QED_AIOCB_* bits ORed together */ diff --git a/block/rbd.c b/block/rbd.c index 0106fea..6f9eb6f 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -71,7 +71,6 @@ typedef enum { typedef struct RBDAIOCB { BlockAIOCB common; - QEMUBH *bh; int64_t ret; QEMUIOVector *qiov; char *bounce; @@ -602,7 +601,6 @@ static const AIOCBInfo rbd_aiocb_info = { static void rbd_finish_bh(void *opaque) { RADOSCB *rcb = opaque; - qemu_bh_delete(rcb->acb->bh); qemu_rbd_complete_aio(rcb); } @@ -621,9 +619,8 @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb) rcb->ret = rbd_aio_get_return_value(c); rbd_aio_release(c); - acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs), - rbd_finish_bh, rcb); - qemu_bh_schedule(acb->bh); + aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs), + rbd_finish_bh, rcb); } static int rbd_aio_discard_wrapper(rbd_image_t image, @@ -679,7 +676,6 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs, acb->ret = 0; acb->error = 0; acb->s = s; - acb->bh = NULL; if (cmd == RBD_AIO_WRITE) { qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size); diff --git a/blockjob.c b/blockjob.c index a167f96..43fecbe 100644 --- a/blockjob.c +++ b/blockjob.c @@ -588,7 +588,6 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err, typedef struct { BlockJob *job; - QEMUBH *bh; AioContext *aio_context; BlockJobDeferToMainLoopFn *fn; void *opaque; @@ -599,8 +598,6 @@ static void block_job_defer_to_main_loop_bh(void *opaque) BlockJobDeferToMainLoopData *data = opaque; AioContext *aio_context; - qemu_bh_delete(data->bh); - /* Prevent race with block_job_defer_to_main_loop() */ aio_context_acquire(data->aio_context); @@ -624,13 +621,13 @@ void block_job_defer_to_main_loop(BlockJob *job, { BlockJobDeferToMainLoopData *data = g_malloc(sizeof(*data)); data->job = job; - data->bh = qemu_bh_new(block_job_defer_to_main_loop_bh, data); data->aio_context = blk_get_aio_context(job->blk); data->fn = fn; data->opaque = opaque; job->deferred_to_main_loop = true; - qemu_bh_schedule(data->bh); + aio_bh_schedule_oneshot(qemu_get_aio_context(), + block_job_defer_to_main_loop_bh, data); } BlockJobTxn *block_job_txn_new(void) -- 2.7.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] block: use aio_bh_schedule_oneshot 2016-10-03 16:14 ` [Qemu-devel] [PATCH 2/2] block: use aio_bh_schedule_oneshot Paolo Bonzini @ 2016-10-05 13:16 ` Stefan Hajnoczi 0 siblings, 0 replies; 10+ messages in thread From: Stefan Hajnoczi @ 2016-10-05 13:16 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel, kwolf, famz [-- Attachment #1: Type: text/plain, Size: 958 bytes --] On Mon, Oct 03, 2016 at 06:14:16PM +0200, Paolo Bonzini wrote: > This simplifies bottom half handlers by removing calls to qemu_bh_delete and > thus removing the need to stash the bottom half pointer in the opaque > datum. > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > block/archipelago.c | 5 +---- > block/blkdebug.c | 7 +------ > block/blkverify.c | 8 ++------ > block/block-backend.c | 23 +++++++---------------- > block/curl.c | 7 +------ > block/gluster.c | 6 +----- > block/io.c | 11 +++-------- > block/iscsi.c | 7 ++----- > block/nfs.c | 7 ++----- > block/null.c | 5 +---- > block/qed.c | 6 ++---- > block/qed.h | 1 - > block/rbd.c | 8 ++------ > blockjob.c | 7 ++----- > 14 files changed, 27 insertions(+), 81 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 455 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 0/2] block: introduce and use aio_bh_schedule_oneshot 2016-10-03 16:14 [Qemu-devel] [PATCH 0/2] block: introduce and use aio_bh_schedule_oneshot Paolo Bonzini 2016-10-03 16:14 ` [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot Paolo Bonzini 2016-10-03 16:14 ` [Qemu-devel] [PATCH 2/2] block: use aio_bh_schedule_oneshot Paolo Bonzini @ 2016-10-05 11:08 ` Kevin Wolf 2 siblings, 0 replies; 10+ messages in thread From: Kevin Wolf @ 2016-10-05 11:08 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel, famz, stefanha Am 03.10.2016 um 18:14 hat Paolo Bonzini geschrieben: > This simplifies a bit using the bottom half API in the common > case of one-shot bottom halves, that are created once per usage. > This patch comes from the multiqueue series. Thanks, applied to the block branch. Kevin ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-10-05 15:26 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-10-03 16:14 [Qemu-devel] [PATCH 0/2] block: introduce and use aio_bh_schedule_oneshot Paolo Bonzini 2016-10-03 16:14 ` [Qemu-devel] [PATCH 1/2] async: add aio_bh_schedule_oneshot Paolo Bonzini 2016-10-05 13:13 ` Stefan Hajnoczi 2016-10-05 13:55 ` Paolo Bonzini 2016-10-05 14:20 ` Kevin Wolf 2016-10-05 14:25 ` Paolo Bonzini 2016-10-05 15:26 ` Kevin Wolf 2016-10-03 16:14 ` [Qemu-devel] [PATCH 2/2] block: use aio_bh_schedule_oneshot Paolo Bonzini 2016-10-05 13:16 ` Stefan Hajnoczi 2016-10-05 11:08 ` [Qemu-devel] [PATCH 0/2] block: introduce and " Kevin Wolf
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).