summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block.c34
-rw-r--r--include/block/block.h1
-rw-r--r--include/block/block_int.h1
-rw-r--r--migration/migration.c7
-rw-r--r--qmp.c12
5 files changed, 55 insertions, 0 deletions
diff --git a/block.c b/block.c
index 95b2967192..5709d3ddb4 100644
--- a/block.c
+++ b/block.c
@@ -3303,6 +3303,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_INACTIVE;
+ 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 2b7d33c78e..25f36dcc74 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -369,6 +369,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 256609dd3d..428fa3397e 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 bc611e453b..aaca451cf8 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1422,7 +1422,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;
}
@@ -1542,6 +1546,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 3ff6db79b9..53affe2cfd 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 {