@@ -2177,16 +2177,20 @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
int64_t pos, int size)
{
- int ret;
+ int ret, ret2;
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
ret = bdrv_save_vmstate(blk_bs(blk), buf, pos, size);
+ ret2 = bdrv_finalize_vmstate(blk_bs(blk));
if (ret < 0) {
return ret;
}
+ if (ret2 < 0) {
+ return ret2;
+ }
if (!blk->enable_write_cache) {
ret = bdrv_flush(blk_bs(blk));
@@ -2724,6 +2724,21 @@ int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
return bdrv_rw_vmstate(bs, qiov, pos, true);
}
+static int coroutine_fn bdrv_co_finalize_vmstate(BlockDriverState *bs)
+{
+ return 0;
+}
+
+static int coroutine_fn bdrv_finalize_vmstate_co_entry(void *opaque)
+{
+ return bdrv_co_finalize_vmstate(opaque);
+}
+
+int bdrv_finalize_vmstate(BlockDriverState *bs)
+{
+ return bdrv_run_co(bs, bdrv_finalize_vmstate_co_entry, bs);
+}
+
/**************************************************************/
/* async I/Os */
@@ -572,6 +572,11 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size);
+/*
+ * bdrv_finalize_vmstate() is mandatory to commit vmstate changes if
+ * bdrv_save_vmstate() was ever called.
+ */
+int bdrv_finalize_vmstate(BlockDriverState *bs);
void bdrv_img_create(const char *filename, const char *fmt,
const char *base_filename, const char *base_fmt,
@@ -150,6 +150,10 @@ static ssize_t block_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
static int bdrv_fclose(void *opaque, Error **errp)
{
+ int err = bdrv_finalize_vmstate(opaque);
+ if (err < 0) {
+ return err;
+ }
return bdrv_flush(opaque);
}