On Thu, Mar 16, 2017 at 05:23:50PM -0400, John Snow wrote: > Allow block backends to forward drain requests to their devices/users. > The initial intended purpose for this patch is to allow BBs to forward > requests along to BlockJobs, which will want to pause if their associated > BB has entered a drained region. > > Signed-off-by: John Snow <js...@redhat.com> > --- > block/block-backend.c | 24 ++++++++++++++++++++++-- > include/sysemu/block-backend.h | 8 ++++++++ > 2 files changed, 30 insertions(+), 2 deletions(-) > > diff --git a/block/block-backend.c b/block/block-backend.c > index 5742c09..dec4a1c 100644 > --- a/block/block-backend.c > +++ b/block/block-backend.c > @@ -65,6 +65,8 @@ struct BlockBackend { > bool allow_write_beyond_eof; > > NotifierList remove_bs_notifiers, insert_bs_notifiers; > + > + int quiesce_counter; > }; > > typedef struct BlockBackendAIOCB { > @@ -699,12 +701,17 @@ void blk_set_dev_ops(BlockBackend *blk, const > BlockDevOps *ops, > void *opaque) > { > /* All drivers that use blk_set_dev_ops() are qdevified and we want to > keep > - * it that way, so we can assume blk->dev is a DeviceState if > blk->dev_ops > - * is set. */ > + * it that way, so we can assume blk->dev, if present, is a DeviceState > if > + * blk->dev_ops is set. Non-device users may use dev_ops without device. > */ > assert(!blk->legacy_dev); > > blk->dev_ops = ops; > blk->dev_opaque = opaque; > + > + /* Are we currently quiesced? Should we enforce this right now? */ > + if (blk->quiesce_counter && ops->drained_begin) { > + ops->drained_begin(opaque); > + } > } > > /* > @@ -1870,6 +1877,12 @@ static void blk_root_drained_begin(BdrvChild *child) > { > BlockBackend *blk = child->opaque; > > + if (++blk->quiesce_counter == 1) { > + if (blk->dev_ops && blk->dev_ops->drained_begin) { > + blk->dev_ops->drained_begin(blk->dev_opaque); > + } > + } > + > /* Note that blk->root may not be accessible here yet if we are just > * attaching to a BlockDriverState that is drained. Use child instead. */ > > @@ -1881,7 +1894,14 @@ static void blk_root_drained_begin(BdrvChild *child) > static void blk_root_drained_end(BdrvChild *child) > { > BlockBackend *blk = child->opaque; > + assert(blk->quiesce_counter); > > assert(blk->public.io_limits_disabled); > --blk->public.io_limits_disabled; > + > + if (--blk->quiesce_counter == 0) { > + if (blk->dev_ops && blk->dev_ops->drained_end) { > + blk->dev_ops->drained_end(blk->dev_opaque); > + } > + } > } > diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h > index 096c17f..7462228 100644 > --- a/include/sysemu/block-backend.h > +++ b/include/sysemu/block-backend.h > @@ -58,6 +58,14 @@ typedef struct BlockDevOps { > * Runs when the size changed (e.g. monitor command block_resize) > */ > void (*resize_cb)(void *opaque); > + /* > + * Runs when the backend receives a drain request. > + */ > + void (*drained_begin)(void *opaque); > + /* > + * Runs when the backend's last drain request ends. > + */ > + void (*drained_end)(void *opaque); > } BlockDevOps; > > /* This struct is embedded in (the private) BlockBackend struct and contains > -- > 2.9.3 >
Reviewed-by: Jeff Cody <jc...@redhat.com>