Add a possibility for safe behavior: stop on first error end report in in errp.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- block/qcow2.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index ccfcd0db05..8ad555feb7 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2678,13 +2678,29 @@ fail_nometa: return ret; } -static int qcow2_inactivate(BlockDriverState *bs) +/* + * With force=true, ignore failures and just print them. Don't set errp, but + * still return a value < 0 in case when something failed. + * + * With force=false, return error < 0 and set errp on first failure. Nothing is + * printed. + */ +static int qcow2_do_inactivate(BlockDriverState *bs, bool force, Error **errp) { int ret, result = 0; + bool ok; Error *local_err = NULL; - qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err); - if (local_err != NULL) { + if (force) { + errp = &local_err; + } + + ok = qcow2_store_persistent_dirty_bitmaps(bs, true, errp); + if (!ok) { + if (!force) { + return -EINVAL; + } + assert(local_err); result = -EINVAL; error_reportf_err(local_err, "Lost persistent bitmaps during " "inactivation of node '%s': ", @@ -2692,8 +2708,11 @@ static int qcow2_inactivate(BlockDriverState *bs) local_err = NULL; } - ret = qcow2_flush_caches(bs, true, &local_err); + ret = qcow2_flush_caches(bs, true, errp); if (ret < 0) { + if (!force) { + return ret; + } result = ret; error_report_err(local_err); local_err = NULL; @@ -2702,14 +2721,25 @@ static int qcow2_inactivate(BlockDriverState *bs) if (result == 0 && bdrv_is_writable(bs)) { ret = qcow2_mark_clean(bs); if (ret < 0) { - error_report("Failed to mark qcow2 node '%s' clean", - bdrv_get_device_or_node_name(bs)); + error_setg(errp, "Failed to mark qcow2 node '%s' clean", + bdrv_get_device_or_node_name(bs)); + if (!force) { + return ret; + } + result = ret; + error_report_err(local_err); + local_err = NULL; } } return result; } +static int qcow2_inactivate(BlockDriverState *bs) +{ + return qcow2_do_inactivate(bs, true, &error_abort); +} + static void qcow2_close(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; -- 2.31.1