summaryrefslogtreecommitdiff
path: root/block/block-backend.c
diff options
context:
space:
mode:
authorJohn Snow <jsnow@redhat.com>2017-03-16 17:23:50 -0400
committerJeff Cody <jcody@redhat.com>2017-03-22 13:26:27 -0400
commitf4d9cc88ee69a5b04a843424e50f466e36fcad4e (patch)
treea2d8777a5e230efd54adfadd6020f8a1ab77e5b8 /block/block-backend.c
parente3796a245ad0efa65ca8d2dc6424562a8fbaeb6a (diff)
downloadqemu-f4d9cc88ee69a5b04a843424e50f466e36fcad4e.tar.gz
block-backend: add drained_begin / drained_end ops
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 <jsnow@redhat.com> Reviewed-by: Jeff Cody <jcody@redhat.com> Message-id: 20170316212351.13797-3-jsnow@redhat.com Signed-off-by: Jeff Cody <jcody@redhat.com>
Diffstat (limited to 'block/block-backend.c')
-rw-r--r--block/block-backend.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/block/block-backend.c b/block/block-backend.c
index 5742c09c2c..0b6377332c 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);
+ }
+ }
}