From: Olga Krishtal <okrish...@virtuozzo.com> If image is opened for writing and it was not closed correctly (the image is dirty) we have to check and repair it. By default the option is off.
bdrv_is_opened_unclean - cheks if the image is dirty This callbsck will be used to ensure that image was closed correctly, and if not - to check and repair it. Signed-off-by: Olga Krishtal <okrish...@virtuozzo.com> Signed-off-by: Denis V. Lunev <d...@openvz.org> CC: Kevin Wolf <kw...@redhat.com> CC: Max Reitz <mre...@redhat.com> CC: Eric Blake <ebl...@redhat.com> CC: Fam Zheng <f...@redhat.com> --- block.c | 32 ++++++++++++++++++++++++++++++++ include/block/block.h | 1 + include/block/block_int.h | 1 + 3 files changed, 34 insertions(+) diff --git a/block.c b/block.c index 74228b8..1f704f5 100644 --- a/block.c +++ b/block.c @@ -903,6 +903,12 @@ static QemuOptsList bdrv_runtime_opts = { .help = "How to lock the image: none or lockfile", .def_value_str = "none", }, + { + .name = "check", + .type = QEMU_OPT_BOOL, + .help = "Check and repair the image if it is unclean", + .def_value_str = "off", + }, { /* end of list */ } }, }; @@ -1042,6 +1048,16 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file, } } + if (!bs->read_only && qemu_opt_get_bool_del(opts, "check", true) && + bdrv_is_opened_unclean(bs) && !(flags | BDRV_O_CHECK)) { + BdrvCheckResult result = {0}; + ret = bdrv_check(bs, &result, BDRV_FIX_ERRORS); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not repair dirty image"); + bdrv_close(bs); + goto fail_opts; + } + } if (bs->encrypted) { error_report("Encrypted images are deprecated"); error_printf("Support for them will be removed in a future release.\n" @@ -4361,3 +4377,19 @@ int bdrv_lock_image(BlockDriverState *bs, BdrvLockImage lock) } return -EOPNOTSUPP; } + +bool bdrv_is_opened_unclean(BlockDriverState *bs) +{ + BlockDriver *drv = bs->drv; + if (drv != NULL && drv->bdrv_is_opened_unclean != NULL) { + return drv->bdrv_is_opened_unclean(bs); + } + if (bs->file == NULL) { + return false; + } + drv = bs->file->bs->drv; + if (drv != NULL && drv->bdrv_is_opened_unclean != NULL) { + return drv->bdrv_is_opened_unclean; + } + return false; +} diff --git a/include/block/block.h b/include/block/block.h index 27fc434..c366990 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -507,6 +507,7 @@ void bdrv_dirty_iter_init(BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi); void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset); int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); int bdrv_lock_image(BlockDriverState *bs, BdrvLockImage lock); +bool bdrv_is_opened_unclean(BlockDriverState *bs); void bdrv_enable_copy_on_read(BlockDriverState *bs); void bdrv_disable_copy_on_read(BlockDriverState *bs); diff --git a/include/block/block_int.h b/include/block/block_int.h index 755f342..fc3f4a6 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -137,6 +137,7 @@ struct BlockDriver { int (*bdrv_make_empty)(BlockDriverState *bs); int (*bdrv_lock_image)(BlockDriverState *bs, BdrvLockImage lock); + bool (*bdrv_is_opened_unclean)(BlockDriverState *bs); void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options); /* aio */ -- 2.1.4