[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 05/10] block: Inactivate BDS when migration complete
From: |
Kevin Wolf |
Subject: |
[Qemu-block] [PATCH 05/10] block: Inactivate BDS when migration completes |
Date: |
Tue, 22 Dec 2015 17:46:21 +0100 |
So far, live migration with shared storage meant that the image is in a
not-really-ready don't-touch-me state on the destination while the
source is still actively using it, but after completing the migration,
the image was fully opened on both sides. This is bad.
This patch adds a block driver callback to inactivate images on the
source before completing the migration. Inactivation means that it goes
to a state as if it was just live migrated to the qemu instance on the
source (i.e. BDRV_O_INCOMING is set). You're then supposed to continue
either on the source or on the destination, which takes ownership of the
image.
A typical migration looks like this now with respect to disk images:
1. Destination qemu is started, the image is opened with
BDRV_O_INCOMING. The image is fully opened on the source.
2. Migration is about to complete. The source flushes the image and
inactivates it. Now both sides have the image opened with
BDRV_O_INCOMING and are expecting the other side to still modify it.
3. One side (the destination on success) continues and calls
bdrv_invalidate_all() in order to take ownership of the image again.
This removes BDRV_O_INCOMING on the resuming side; the flag remains
set on the other side.
This ensures that the same image isn't written to by both instances
(unless both are resumed, but then you get what you deserve). This is
important because .bdrv_close for non-BDRV_O_INCOMING images could write
to the image file, which is definitely forbidden while another host is
using the image.
Signed-off-by: Kevin Wolf <address@hidden>
---
block.c | 34 ++++++++++++++++++++++++++++++++++
include/block/block.h | 1 +
include/block/block_int.h | 1 +
migration/migration.c | 7 +++++++
qmp.c | 12 ++++++++++++
5 files changed, 55 insertions(+)
diff --git a/block.c b/block.c
index 554ed64..8b4288e 100644
--- a/block.c
+++ b/block.c
@@ -3304,6 +3304,40 @@ void bdrv_invalidate_cache_all(Error **errp)
}
}
+static int bdrv_inactivate(BlockDriverState *bs)
+{
+ int ret;
+
+ if (bs->drv->bdrv_inactivate) {
+ ret = bs->drv->bdrv_inactivate(bs);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ bs->open_flags |= BDRV_O_INCOMING;
+ return 0;
+}
+
+int bdrv_inactivate_all(void)
+{
+ BlockDriverState *bs;
+ int ret;
+
+ QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(aio_context);
+ ret = bdrv_inactivate(bs);
+ aio_context_release(aio_context);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
/**************************************************************/
/* removable device support */
diff --git a/include/block/block.h b/include/block/block.h
index db8e096..0d00ac1 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -368,6 +368,7 @@ BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
/* Invalidate any cached metadata used by image formats */
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
void bdrv_invalidate_cache_all(Error **errp);
+int bdrv_inactivate_all(void);
/* Ensure contents are flushed to disk. */
int bdrv_flush(BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 9a1c466..a35ddc9 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -172,6 +172,7 @@ struct BlockDriver {
* Invalidate any cached meta-data.
*/
void (*bdrv_invalidate_cache)(BlockDriverState *bs, Error **errp);
+ int (*bdrv_inactivate)(BlockDriverState *bs);
/*
* Flushes all data that was already written to the OS all the way down to
diff --git a/migration/migration.c b/migration/migration.c
index c842499..309aa98 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1416,7 +1416,11 @@ static int postcopy_start(MigrationState *ms, bool
*old_vm_running)
*old_vm_running = runstate_is_running();
global_state_store();
ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ if (ret < 0) {
+ goto fail;
+ }
+ ret = bdrv_inactivate_all();
if (ret < 0) {
goto fail;
}
@@ -1536,6 +1540,9 @@ static void migration_completion(MigrationState *s, int
current_active_state,
if (!ret) {
ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
if (ret >= 0) {
+ ret = bdrv_inactivate_all();
+ }
+ if (ret >= 0) {
qemu_file_set_rate_limit(s->file, INT64_MAX);
qemu_savevm_state_complete_precopy(s->file, false);
}
diff --git a/qmp.c b/qmp.c
index 0a1fa19..39b8da1 100644
--- a/qmp.c
+++ b/qmp.c
@@ -192,6 +192,18 @@ void qmp_cont(Error **errp)
}
}
+ /* Continuing after completed migration. Images have been inactivated to
+ * allow the destination to take control. Need to get control back now. */
+ if (runstate_check(RUN_STATE_FINISH_MIGRATE) ||
+ runstate_check(RUN_STATE_POSTMIGRATE))
+ {
+ bdrv_invalidate_cache_all(&local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
if (runstate_check(RUN_STATE_INMIGRATE)) {
autostart = 1;
} else {
--
1.8.3.1
- [Qemu-block] [PATCH 00/10] qcow2: Implement image locking, Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 02/10] qcow2: Write full header on image creation, Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 01/10] qcow2: Write feature table only for v3 images, Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 03/10] block: Assert no write requests under BDRV_O_INCOMING, Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 04/10] block: Fix error path in bdrv_invalidate_cache(), Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 05/10] block: Inactivate BDS when migration completes,
Kevin Wolf <=
- [Qemu-block] [PATCH 07/10] qcow2: Implement .bdrv_inactivate, Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 08/10] qcow2: Fix BDRV_O_INCOMING handling in qcow2_invalidate_cache(), Kevin Wolf, 2015/12/22
- [Qemu-block] [PATCH 06/10] qemu-img: Prepare for locked images, Kevin Wolf, 2015/12/22