block: Add error handling to bdrv_invalidate_cache()

If it returns an error, the migrated VM will not be started, but qemu
exits with an error message.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
This commit is contained in:
Kevin Wolf 2014-03-12 15:59:16 +01:00
parent 059b3527f0
commit 5a8a30db47
7 changed files with 76 additions and 18 deletions

28
block.c
View File

@ -4781,27 +4781,43 @@ flush_parent:
return bdrv_co_flush(bs->file); return bdrv_co_flush(bs->file);
} }
void bdrv_invalidate_cache(BlockDriverState *bs) void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
{ {
Error *local_err = NULL;
int ret;
if (!bs->drv) { if (!bs->drv) {
return; return;
} }
if (bs->drv->bdrv_invalidate_cache) { if (bs->drv->bdrv_invalidate_cache) {
bs->drv->bdrv_invalidate_cache(bs); bs->drv->bdrv_invalidate_cache(bs, &local_err);
} else if (bs->file) { } else if (bs->file) {
bdrv_invalidate_cache(bs->file); bdrv_invalidate_cache(bs->file, &local_err);
}
if (local_err) {
error_propagate(errp, local_err);
return;
} }
refresh_total_sectors(bs, bs->total_sectors); ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not refresh total sector count");
return;
}
} }
void bdrv_invalidate_cache_all(void) void bdrv_invalidate_cache_all(Error **errp)
{ {
BlockDriverState *bs; BlockDriverState *bs;
Error *local_err = NULL;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) { QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
bdrv_invalidate_cache(bs); bdrv_invalidate_cache(bs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
} }
} }

View File

@ -1156,7 +1156,7 @@ static void qcow2_close(BlockDriverState *bs)
qcow2_free_snapshots(bs); qcow2_free_snapshots(bs);
} }
static void qcow2_invalidate_cache(BlockDriverState *bs) static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
int flags = s->flags; int flags = s->flags;
@ -1164,6 +1164,8 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
AES_KEY aes_decrypt_key; AES_KEY aes_decrypt_key;
uint32_t crypt_method = 0; uint32_t crypt_method = 0;
QDict *options; QDict *options;
Error *local_err = NULL;
int ret;
/* /*
* Backing files are read-only which makes all of their metadata immutable, * Backing files are read-only which makes all of their metadata immutable,
@ -1178,11 +1180,25 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
qcow2_close(bs); qcow2_close(bs);
bdrv_invalidate_cache(bs->file); bdrv_invalidate_cache(bs->file, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
memset(s, 0, sizeof(BDRVQcowState)); memset(s, 0, sizeof(BDRVQcowState));
options = qdict_clone_shallow(bs->options); options = qdict_clone_shallow(bs->options);
qcow2_open(bs, options, flags, NULL);
ret = qcow2_open(bs, options, flags, &local_err);
if (local_err) {
error_setg(errp, "Could not reopen qcow2 layer: %s",
error_get_pretty(local_err));
error_free(local_err);
return;
} else if (ret < 0) {
error_setg_errno(errp, -ret, "Could not reopen qcow2 layer");
return;
}
QDECREF(options); QDECREF(options);

View File

@ -1558,16 +1558,31 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
return ret; return ret;
} }
static void bdrv_qed_invalidate_cache(BlockDriverState *bs) static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
{ {
BDRVQEDState *s = bs->opaque; BDRVQEDState *s = bs->opaque;
Error *local_err = NULL;
int ret;
bdrv_qed_close(bs); bdrv_qed_close(bs);
bdrv_invalidate_cache(bs->file); bdrv_invalidate_cache(bs->file, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
memset(s, 0, sizeof(BDRVQEDState)); memset(s, 0, sizeof(BDRVQEDState));
bdrv_qed_open(bs, NULL, bs->open_flags, NULL); ret = bdrv_qed_open(bs, NULL, bs->open_flags, &local_err);
if (local_err) {
error_setg(errp, "Could not reopen qed layer: %s",
error_get_pretty(local_err));
error_free(local_err);
return;
} else if (ret < 0) {
error_setg_errno(errp, -ret, "Could not reopen qed layer");
return;
}
} }
static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result, static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,

View File

@ -625,13 +625,18 @@ static int64_t quorum_getlength(BlockDriverState *bs)
return result; return result;
} }
static void quorum_invalidate_cache(BlockDriverState *bs) static void quorum_invalidate_cache(BlockDriverState *bs, Error **errp)
{ {
BDRVQuorumState *s = bs->opaque; BDRVQuorumState *s = bs->opaque;
Error *local_err = NULL;
int i; int i;
for (i = 0; i < s->num_children; i++) { for (i = 0; i < s->num_children; i++) {
bdrv_invalidate_cache(s->bs[i]); bdrv_invalidate_cache(s->bs[i], &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
} }
} }

View File

@ -329,8 +329,8 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque); BlockDriverCompletionFunc *cb, void *opaque);
/* Invalidate any cached metadata used by image formats */ /* Invalidate any cached metadata used by image formats */
void bdrv_invalidate_cache(BlockDriverState *bs); void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
void bdrv_invalidate_cache_all(void); void bdrv_invalidate_cache_all(Error **errp);
void bdrv_clear_incoming_migration_all(void); void bdrv_clear_incoming_migration_all(void);

View File

@ -153,7 +153,7 @@ struct BlockDriver {
/* /*
* Invalidate any cached meta-data. * Invalidate any cached meta-data.
*/ */
void (*bdrv_invalidate_cache)(BlockDriverState *bs); void (*bdrv_invalidate_cache)(BlockDriverState *bs, Error **errp);
/* /*
* Flushes all data that was already written to the OS all the way down to * Flushes all data that was already written to the OS all the way down to

View File

@ -101,6 +101,7 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
static void process_incoming_migration_co(void *opaque) static void process_incoming_migration_co(void *opaque)
{ {
QEMUFile *f = opaque; QEMUFile *f = opaque;
Error *local_err = NULL;
int ret; int ret;
ret = qemu_loadvm_state(f); ret = qemu_loadvm_state(f);
@ -115,7 +116,12 @@ static void process_incoming_migration_co(void *opaque)
bdrv_clear_incoming_migration_all(); bdrv_clear_incoming_migration_all();
/* Make sure all file formats flush their mutable metadata */ /* Make sure all file formats flush their mutable metadata */
bdrv_invalidate_cache_all(); bdrv_invalidate_cache_all(&local_err);
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
exit(EXIT_FAILURE);
}
if (autostart) { if (autostart) {
vm_start(); vm_start();