On Wed, Nov 29, 2017 at 10:49:49PM +0800, Fam Zheng wrote: > diff --git a/util/async.c b/util/async.c > index 4dd9d95a9e..cca0efd263 100644 > --- a/util/async.c > +++ b/util/async.c > @@ -402,6 +402,7 @@ AioContext *aio_context_new(Error **errp) > AioContext *ctx; > > ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); > + QTAILQ_INIT(&ctx->drain_ops); > aio_context_setup(ctx); > > ret = event_notifier_init(&ctx->notifier, false); > @@ -506,3 +507,75 @@ void aio_context_release(AioContext *ctx) > { > qemu_rec_mutex_unlock(&ctx->lock); > } > + > +/* Called with ctx->lock */ > +void aio_context_drained_begin(AioContext *ctx) > +{ > + AioDrainOps *ops; > + > + /* TODO: When all external fds are handled in the following drain_ops > + * callbacks, aio_disable_external can be dropped. */ > + aio_disable_external(ctx); > +restart: > + ctx->drain_ops_updated = false; > + QTAILQ_FOREACH(ops, &ctx->drain_ops, next) { > + ops->drained_begin(ops->opaque); > + if (ctx->drain_ops_updated) { > + goto restart;
drained_begin() can be called multiple times. This needs to be clearly documented to avoid surprises. > + } > + } > +} > + > +/* Called with ctx->lock */ > +void aio_context_drained_end(AioContext *ctx) > +{ > + AioDrainOps *ops; > + > +restart: > + ctx->drain_ops_updated = false; > + QTAILQ_FOREACH(ops, &ctx->drain_ops, next) { > + if (ops->is_new) { > + continue; > + } > + ops->drained_end(ops->opaque); drained_end() can be called multiple times. This needs to be clearly documented to avoid surprises. > + if (ctx->drain_ops_updated) { > + goto restart; > + } > + } > + if (aio_enable_external(ctx)) { > + QTAILQ_FOREACH(ops, &ctx->drain_ops, next) { > + ops->is_new = false; > + } > + } This is weird, aio_context_drained_end() has nesting support for ->is_new but not for ->drained_end() calls. I'm not sure where you're going with these semantics yet.
signature.asc
Description: PGP signature