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


Reply via email to