From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 01/10] block: Ignore guest dev permissions during incoming migration
Date: Fri, 7 Apr 2017 15:47:36 +0200 [thread overview]
Message-ID: <1491572865-8549-2-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1491572865-8549-1-git-send-email-kwolf@redhat.com>
Usually guest devices don't like other writers to the same image, so
they use blk_set_perm() to prevent this from happening. In the migration
phase before the VM is actually running, though, they don't have a
problem with writes to the image. On the other hand, storage migration
needs to be able to write to the image in this phase, so the restrictive
blk_set_perm() call of qdev devices breaks it.
This patch flags all BlockBackends with a qdev device as
blk->disable_perm during incoming migration, which means that the
requested permissions are stored in the BlockBackend, but not actually
applied to its root node yet.
Once migration has finished and the VM should be resumed, the
permissions are applied. If they cannot be applied (e.g. because the NBD
server used for block migration hasn't been shut down), resuming the VM
fails.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Tested-by: Kashyap Chamarthy <kchamart@redhat.com>
---
block/block-backend.c | 40 +++++++++++++++++++++++++++++++++++++++-
include/block/block.h | 2 ++
migration/migration.c | 8 ++++++++
qmp.c | 6 ++++++
4 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index 0b63773..18ece99 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -61,6 +61,7 @@ struct BlockBackend {
uint64_t perm;
uint64_t shared_perm;
+ bool disable_perm;
bool allow_write_beyond_eof;
@@ -578,7 +579,7 @@ int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
{
int ret;
- if (blk->root) {
+ if (blk->root && !blk->disable_perm) {
ret = bdrv_child_try_set_perm(blk->root, perm, shared_perm, errp);
if (ret < 0) {
return ret;
@@ -597,15 +598,52 @@ void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
*shared_perm = blk->shared_perm;
}
+/*
+ * Notifies the user of all BlockBackends that migration has completed. qdev
+ * devices can tighten their permissions in response (specifically revoke
+ * shared write permissions that we needed for storage migration).
+ *
+ * If an error is returned, the VM cannot be allowed to be resumed.
+ */
+void blk_resume_after_migration(Error **errp)
+{
+ BlockBackend *blk;
+ Error *local_err = NULL;
+
+ for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
+ if (!blk->disable_perm) {
+ continue;
+ }
+
+ blk->disable_perm = false;
+
+ blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ blk->disable_perm = true;
+ return;
+ }
+ }
+}
+
static int blk_do_attach_dev(BlockBackend *blk, void *dev)
{
if (blk->dev) {
return -EBUSY;
}
+
+ /* While migration is still incoming, we don't need to apply the
+ * permissions of guest device BlockBackends. We might still have a block
+ * job or NBD server writing to the image for storage migration. */
+ if (runstate_check(RUN_STATE_INMIGRATE)) {
+ blk->disable_perm = true;
+ }
+
blk_ref(blk);
blk->dev = dev;
blk->legacy_dev = false;
blk_iostatus_reset(blk);
+
return 0;
}
diff --git a/include/block/block.h b/include/block/block.h
index 5149260..3e09222 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -366,6 +366,8 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
void bdrv_invalidate_cache_all(Error **errp);
int bdrv_inactivate_all(void);
+void blk_resume_after_migration(Error **errp);
+
/* Ensure contents are flushed to disk. */
int bdrv_flush(BlockDriverState *bs);
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
diff --git a/migration/migration.c b/migration/migration.c
index 54060f7..ad4036f 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -349,6 +349,14 @@ static void process_incoming_migration_bh(void *opaque)
exit(EXIT_FAILURE);
}
+ /* If we get an error here, just don't restart the VM yet. */
+ blk_resume_after_migration(&local_err);
+ if (local_err) {
+ error_free(local_err);
+ local_err = NULL;
+ autostart = false;
+ }
+
/*
* This must happen after all error conditions are dealt with and
* we're sure the VM is going to be running on this host.
diff --git a/qmp.c b/qmp.c
index fa82b59..a744e44 100644
--- a/qmp.c
+++ b/qmp.c
@@ -207,6 +207,12 @@ void qmp_cont(Error **errp)
}
}
+ blk_resume_after_migration(&local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
if (runstate_check(RUN_STATE_INMIGRATE)) {
autostart = 1;
} else {
--
1.8.3.1
next prev parent reply other threads:[~2017-04-07 13:47 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-07 13:47 [Qemu-devel] [PULL 00/10] Block layer fixes for 2.9.0-rc4 Kevin Wolf
2017-04-07 13:47 ` Kevin Wolf [this message]
2017-04-07 13:47 ` [Qemu-devel] [PULL 02/10] commit: Set commit_top_bs->aio_context Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 03/10] commit: Set commit_top_bs->total_sectors Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 04/10] block/mirror: Fix use-after-free Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 05/10] iotests: Add mirror tests for orphaned source Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 06/10] qemu-img: img_create does not support image-opts, fix docs Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 07/10] block: Don't check permissions for copy on read Kevin Wolf
2017-04-07 14:11 ` Eric Blake
2017-04-07 13:47 ` [Qemu-devel] [PULL 08/10] block: Fix unpaired aio_disable_external in external snapshot Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 09/10] block: Assert attached child node has right aio context Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 10/10] mirror: Fix aio context of mirror_top_bs Kevin Wolf
2017-04-07 15:24 ` [Qemu-devel] [PULL 00/10] Block layer fixes for 2.9.0-rc4 Peter Maydell
2017-04-12 23:51 ` no-reply
2017-04-13 0:00 ` Fam Zheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1491572865-8549-2-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.