All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 00/14] block: deal with errp: part I
@ 2021-02-02 12:49 Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 01/14] block: return status from bdrv_append and friends Vladimir Sementsov-Ogievskiy
                   ` (13 more replies)
  0 siblings, 14 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	stefanha, pbonzini, mreitz, jsnow, ari

v7:
08: rebase onto QAPI_LIST_APPEND used, drop r-b

Vladimir Sementsov-Ogievskiy (14):
  block: return status from bdrv_append and friends
  block: use return status of bdrv_append()
  block: check return value of bdrv_open_child and drop error
    propagation
  blockdev: fix drive_backup_prepare() missed error
  block: drop extra error propagation for bdrv_set_backing_hd
  block/mirror: drop extra error propagation in commit_active_start()
  blockjob: return status from block_job_set_speed()
  block/qcow2: qcow2_get_specific_info(): drop error propagation
  block/qcow2-bitmap: improve qcow2_load_dirty_bitmaps() interface
  block/qcow2-bitmap: return status from
    qcow2_store_persistent_dirty_bitmaps
  block/qcow2: read_cache_sizes: return status value
  block/qcow2: simplify qcow2_co_invalidate_cache()
  block/qed: bdrv_qed_do_open: deal with errp
  block/qcow2: refactor qcow2_update_options_prepare error paths

 block/qcow2.h               |  9 ++---
 include/block/block.h       | 12 +++----
 include/block/blockjob.h    |  2 +-
 block.c                     | 70 ++++++++++++++++++++++---------------
 block/backup-top.c          | 23 ++++++------
 block/blkdebug.c            |  6 ++--
 block/blklogwrites.c        | 10 +++---
 block/blkreplay.c           |  6 ++--
 block/blkverify.c           | 11 +++---
 block/commit.c              |  6 ++--
 block/mirror.c              | 18 ++++------
 block/qcow2-bitmap.c        | 65 ++++++++++++++++++----------------
 block/qcow2.c               | 64 +++++++++++++++------------------
 block/qed.c                 | 24 ++++++++-----
 block/quorum.c              |  6 ++--
 blockdev.c                  | 10 +++---
 blockjob.c                  | 18 +++++-----
 tests/test-bdrv-graph-mod.c |  6 ++--
 18 files changed, 179 insertions(+), 187 deletions(-)

-- 
2.29.2



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v7 01/14] block: return status from bdrv_append and friends
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-05 11:16   ` Alberto Garcia
  2021-02-02 12:49 ` [PATCH v7 02/14] block: use return status of bdrv_append() Vladimir Sementsov-Ogievskiy
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	stefanha, pbonzini, mreitz, jsnow, ari

The recommended use of qemu error api assumes returning status together
with setting errp and avoid void functions with errp parameter. Let's
improve bdrv_append and some friends to reduce error-propagation
overhead in further patches.

Choose int return status, because bdrv_replace_node_common() has call
to bdrv_check_update_perm(), which reports int status, which seems
correct to propagate.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 include/block/block.h | 12 ++++-----
 block.c               | 58 +++++++++++++++++++++++++++----------------
 2 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/include/block/block.h b/include/block/block.h
index 81fcaad5ac..da24192901 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -356,10 +356,10 @@ int bdrv_create(BlockDriver *drv, const char* filename,
 int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
 
 BlockDriverState *bdrv_new(void);
-void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
-                 Error **errp);
-void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
-                       Error **errp);
+int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
+                Error **errp);
+int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
+                      Error **errp);
 BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
                                    int flags, Error **errp);
 
@@ -373,8 +373,8 @@ BdrvChild *bdrv_open_child(const char *filename,
                            BdrvChildRole child_role,
                            bool allow_none, Error **errp);
 BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
-void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
-                         Error **errp);
+int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
+                        Error **errp);
 int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
                            const char *bdref_key, Error **errp);
 BlockDriverState *bdrv_open(const char *filename, const char *reference,
diff --git a/block.c b/block.c
index 91a66d4f3e..8a169641de 100644
--- a/block.c
+++ b/block.c
@@ -2827,14 +2827,15 @@ static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
  * Sets the bs->backing link of a BDS. A new reference is created; callers
  * which don't need their own reference any more must call bdrv_unref().
  */
-void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
-                         Error **errp)
+int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
+                        Error **errp)
 {
+    int ret = 0;
     bool update_inherits_from = bdrv_chain_contains(bs, backing_hd) &&
         bdrv_inherits_from_recursive(backing_hd, bs);
 
     if (bdrv_is_backing_chain_frozen(bs, child_bs(bs->backing), errp)) {
-        return;
+        return -EPERM;
     }
 
     if (backing_hd) {
@@ -2853,15 +2854,22 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
 
     bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_of_bds,
                                     bdrv_backing_role(bs), errp);
+    if (!bs->backing) {
+        ret = -EPERM;
+        goto out;
+    }
+
     /* If backing_hd was already part of bs's backing chain, and
      * inherits_from pointed recursively to bs then let's update it to
      * point directly to bs (else it will become NULL). */
-    if (bs->backing && update_inherits_from) {
+    if (update_inherits_from) {
         backing_hd->inherits_from = bs;
     }
 
 out:
     bdrv_refresh_limits(bs, NULL);
+
+    return ret;
 }
 
 /*
@@ -4533,9 +4541,9 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
  * With auto_skip=false the error is returned if from has a parent which should
  * not be updated.
  */
-static void bdrv_replace_node_common(BlockDriverState *from,
-                                     BlockDriverState *to,
-                                     bool auto_skip, Error **errp)
+static int bdrv_replace_node_common(BlockDriverState *from,
+                                    BlockDriverState *to,
+                                    bool auto_skip, Error **errp)
 {
     BdrvChild *c, *next;
     GSList *list = NULL, *p;
@@ -4557,11 +4565,13 @@ static void bdrv_replace_node_common(BlockDriverState *from,
             if (auto_skip) {
                 continue;
             }
+            ret = -EINVAL;
             error_setg(errp, "Should not change '%s' link to '%s'",
                        c->name, from->node_name);
             goto out;
         }
         if (c->frozen) {
+            ret = -EPERM;
             error_setg(errp, "Cannot change '%s' link to '%s'",
                        c->name, from->node_name);
             goto out;
@@ -4592,14 +4602,18 @@ static void bdrv_replace_node_common(BlockDriverState *from,
 
     bdrv_set_perm(to);
 
+    ret = 0;
+
 out:
     g_slist_free(list);
     bdrv_drained_end(from);
     bdrv_unref(from);
+
+    return ret;
 }
 
-void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
-                       Error **errp)
+int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
+                      Error **errp)
 {
     return bdrv_replace_node_common(from, to, true, errp);
 }
@@ -4620,28 +4634,30 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
  * parents of bs_top after bdrv_append() returns. If the caller needs to keep a
  * reference of its own, it must call bdrv_ref().
  */
-void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
-                 Error **errp)
+int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
+                Error **errp)
 {
-    Error *local_err = NULL;
-
-    bdrv_set_backing_hd(bs_new, bs_top, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    int ret = bdrv_set_backing_hd(bs_new, bs_top, errp);
+    if (ret < 0) {
         goto out;
     }
 
-    bdrv_replace_node(bs_top, bs_new, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    ret = bdrv_replace_node(bs_top, bs_new, errp);
+    if (ret < 0) {
         bdrv_set_backing_hd(bs_new, NULL, &error_abort);
         goto out;
     }
 
-    /* bs_new is now referenced by its new parents, we don't need the
-     * additional reference any more. */
+    ret = 0;
+
 out:
+    /*
+     * bs_new is now referenced by its new parents, we don't need the
+     * additional reference any more.
+     */
     bdrv_unref(bs_new);
+
+    return ret;
 }
 
 static void bdrv_delete(BlockDriverState *bs)
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 02/14] block: use return status of bdrv_append()
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 01/14] block: return status from bdrv_append and friends Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation Vladimir Sementsov-Ogievskiy
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	stefanha, pbonzini, mreitz, jsnow, ari

Now bdrv_append returns status and we can drop all the local_err things
around it.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block.c                     |  6 ++----
 block/backup-top.c          | 23 +++++++++++------------
 block/commit.c              |  6 ++----
 block/mirror.c              |  6 ++----
 blockdev.c                  |  6 +++---
 tests/test-bdrv-graph-mod.c |  6 +++---
 6 files changed, 23 insertions(+), 30 deletions(-)

diff --git a/block.c b/block.c
index 8a169641de..48b0de36ff 100644
--- a/block.c
+++ b/block.c
@@ -3118,7 +3118,6 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
     int64_t total_size;
     QemuOpts *opts = NULL;
     BlockDriverState *bs_snapshot = NULL;
-    Error *local_err = NULL;
     int ret;
 
     /* if snapshot, we create a temporary backing file and open it
@@ -3165,9 +3164,8 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
      * order to be able to return one, we have to increase
      * bs_snapshot's refcount here */
     bdrv_ref(bs_snapshot);
-    bdrv_append(bs_snapshot, bs, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    ret = bdrv_append(bs_snapshot, bs, errp);
+    if (ret < 0) {
         bs_snapshot = NULL;
         goto out;
     }
diff --git a/block/backup-top.c b/block/backup-top.c
index 6e7e7bf340..d1253e1aa6 100644
--- a/block/backup-top.c
+++ b/block/backup-top.c
@@ -191,7 +191,8 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
                                          BlockCopyState **bcs,
                                          Error **errp)
 {
-    Error *local_err = NULL;
+    ERRP_GUARD();
+    int ret;
     BDRVBackupTopState *state;
     BlockDriverState *top;
     bool appended = false;
@@ -224,9 +225,9 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
     bdrv_drained_begin(source);
 
     bdrv_ref(top);
-    bdrv_append(top, source, &local_err);
-    if (local_err) {
-        error_prepend(&local_err, "Cannot append backup-top filter: ");
+    ret = bdrv_append(top, source, errp);
+    if (ret < 0) {
+        error_prepend(errp, "Cannot append backup-top filter: ");
         goto fail;
     }
     appended = true;
@@ -236,19 +237,18 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
      * we want.
      */
     state->active = true;
-    bdrv_child_refresh_perms(top, top->backing, &local_err);
-    if (local_err) {
-        error_prepend(&local_err,
-                      "Cannot set permissions for backup-top filter: ");
+    ret = bdrv_child_refresh_perms(top, top->backing, errp);
+    if (ret < 0) {
+        error_prepend(errp, "Cannot set permissions for backup-top filter: ");
         goto fail;
     }
 
     state->cluster_size = cluster_size;
     state->bcs = block_copy_state_new(top->backing, state->target,
                                       cluster_size, perf->use_copy_range,
-                                      write_flags, &local_err);
-    if (local_err) {
-        error_prepend(&local_err, "Cannot create block-copy-state: ");
+                                      write_flags, errp);
+    if (!state->bcs) {
+        error_prepend(errp, "Cannot create block-copy-state: ");
         goto fail;
     }
     *bcs = state->bcs;
@@ -266,7 +266,6 @@ fail:
     }
 
     bdrv_drained_end(source);
-    error_propagate(errp, local_err);
 
     return NULL;
 }
diff --git a/block/commit.c b/block/commit.c
index 71db7ba747..dd9ba87349 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -254,7 +254,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
     BlockDriverState *iter;
     BlockDriverState *commit_top_bs = NULL;
     BlockDriverState *filtered_base;
-    Error *local_err = NULL;
     int64_t base_size, top_size;
     uint64_t base_perms, iter_shared_perms;
     int ret;
@@ -312,10 +311,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 
     commit_top_bs->total_sectors = top->total_sectors;
 
-    bdrv_append(commit_top_bs, top, &local_err);
-    if (local_err) {
+    ret = bdrv_append(commit_top_bs, top, errp);
+    if (ret < 0) {
         commit_top_bs = NULL;
-        error_propagate(errp, local_err);
         goto fail;
     }
 
diff --git a/block/mirror.c b/block/mirror.c
index 8e1ad6eceb..fad2701938 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1560,7 +1560,6 @@ static BlockJob *mirror_start_job(
     BlockDriverState *mirror_top_bs;
     bool target_is_backing;
     uint64_t target_perms, target_shared_perms;
-    Error *local_err = NULL;
     int ret;
 
     if (granularity == 0) {
@@ -1609,12 +1608,11 @@ static BlockJob *mirror_start_job(
      * it alive until block_job_create() succeeds even if bs has no parent. */
     bdrv_ref(mirror_top_bs);
     bdrv_drained_begin(bs);
-    bdrv_append(mirror_top_bs, bs, &local_err);
+    ret = bdrv_append(mirror_top_bs, bs, errp);
     bdrv_drained_end(bs);
 
-    if (local_err) {
+    if (ret < 0) {
         bdrv_unref(mirror_top_bs);
-        error_propagate(errp, local_err);
         return NULL;
     }
 
diff --git a/blockdev.c b/blockdev.c
index b250b9b959..cd438e60e3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1432,6 +1432,7 @@ typedef struct ExternalSnapshotState {
 static void external_snapshot_prepare(BlkActionState *common,
                                       Error **errp)
 {
+    int ret;
     int flags = 0;
     QDict *options = NULL;
     Error *local_err = NULL;
@@ -1591,9 +1592,8 @@ static void external_snapshot_prepare(BlkActionState *common,
      * can fail, so we need to do it in .prepare; undoing it for abort is
      * always possible. */
     bdrv_ref(state->new_bs);
-    bdrv_append(state->new_bs, state->old_bs, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    ret = bdrv_append(state->new_bs, state->old_bs, errp);
+    if (ret < 0) {
         goto out;
     }
     state->overlay_appended = true;
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
index 8cff13830e..c4f7d16039 100644
--- a/tests/test-bdrv-graph-mod.c
+++ b/tests/test-bdrv-graph-mod.c
@@ -101,7 +101,7 @@ static BlockDriverState *pass_through_node(const char *name)
  */
 static void test_update_perm_tree(void)
 {
-    Error *local_err = NULL;
+    int ret;
 
     BlockBackend *root = blk_new(qemu_get_aio_context(),
                                  BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ,
@@ -114,8 +114,8 @@ static void test_update_perm_tree(void)
     bdrv_attach_child(filter, bs, "child", &child_of_bds,
                       BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
 
-    bdrv_append(filter, bs, &local_err);
-    error_free_or_abort(&local_err);
+    ret = bdrv_append(filter, bs, NULL);
+    g_assert_cmpint(ret, <, 0);
 
     blk_unref(root);
 }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 01/14] block: return status from bdrv_append and friends Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 02/14] block: use return status of bdrv_append() Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-12 23:13   ` Eric Blake
  2021-02-02 12:49 ` [PATCH v7 04/14] blockdev: fix drive_backup_prepare() missed error Vladimir Sementsov-Ogievskiy
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

This patch is generated by cocci script:

@@
symbol bdrv_open_child, errp, local_err;
expression file;
@@

  file = bdrv_open_child(...,
-                        &local_err
+                        errp
                        );
- if (local_err)
+ if (!file)
  {
      ...
-     error_propagate(errp, local_err);
      ...
  }

with command

spatch --sp-file x.cocci --macro-file scripts/cocci-macro-file.h \
--in-place --no-show-diff --max-width 80 --use-gitgrep block

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/blkdebug.c     |  6 ++----
 block/blklogwrites.c | 10 ++++------
 block/blkreplay.c    |  6 ++----
 block/blkverify.c    | 11 ++++-------
 block/qcow2.c        |  5 ++---
 block/quorum.c       |  6 ++----
 6 files changed, 16 insertions(+), 28 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 5fe6172da9..315965a013 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -465,7 +465,6 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
 {
     BDRVBlkdebugState *s = bs->opaque;
     QemuOpts *opts;
-    Error *local_err = NULL;
     int ret;
     uint64_t align;
 
@@ -495,10 +494,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
                                bs, &child_of_bds,
                                BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
-                               false, &local_err);
-    if (local_err) {
+                               false, errp);
+    if (!bs->file) {
         ret = -EINVAL;
-        error_propagate(errp, local_err);
         goto out;
     }
 
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index 13ae63983b..b7579370a3 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -157,19 +157,17 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
     /* Open the file */
     bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
                                BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
-                               &local_err);
-    if (local_err) {
+                               errp);
+    if (!bs->file) {
         ret = -EINVAL;
-        error_propagate(errp, local_err);
         goto fail;
     }
 
     /* Open the log file */
     s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_of_bds,
-                                  BDRV_CHILD_METADATA, false, &local_err);
-    if (local_err) {
+                                  BDRV_CHILD_METADATA, false, errp);
+    if (!s->log_file) {
         ret = -EINVAL;
-        error_propagate(errp, local_err);
         goto fail;
     }
 
diff --git a/block/blkreplay.c b/block/blkreplay.c
index 30a0f5d57a..4a247752fd 100644
--- a/block/blkreplay.c
+++ b/block/blkreplay.c
@@ -23,16 +23,14 @@ typedef struct Request {
 static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
                           Error **errp)
 {
-    Error *local_err = NULL;
     int ret;
 
     /* Open the image file */
     bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
                                BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
-                               false, &local_err);
-    if (local_err) {
+                               false, errp);
+    if (!bs->file) {
         ret = -EINVAL;
-        error_propagate(errp, local_err);
         goto fail;
     }
 
diff --git a/block/blkverify.c b/block/blkverify.c
index 4aed53ab59..95ae73e2aa 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -112,7 +112,6 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
 {
     BDRVBlkverifyState *s = bs->opaque;
     QemuOpts *opts;
-    Error *local_err = NULL;
     int ret;
 
     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
@@ -125,20 +124,18 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
                                bs, &child_of_bds,
                                BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
-                               false, &local_err);
-    if (local_err) {
+                               false, errp);
+    if (!bs->file) {
         ret = -EINVAL;
-        error_propagate(errp, local_err);
         goto fail;
     }
 
     /* Open the test file */
     s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options,
                                    "test", bs, &child_of_bds, BDRV_CHILD_DATA,
-                                   false, &local_err);
-    if (local_err) {
+                                   false, errp);
+    if (!s->test_file) {
         ret = -EINVAL;
-        error_propagate(errp, local_err);
         goto fail;
     }
 
diff --git a/block/qcow2.c b/block/qcow2.c
index 5d94f45be9..e8dd42d73b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1611,9 +1611,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
     /* Open external data file */
     s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
                                    &child_of_bds, BDRV_CHILD_DATA,
-                                   true, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+                                   true, errp);
+    if (!s->data_file) {
         ret = -EINVAL;
         goto fail;
     }
diff --git a/block/quorum.c b/block/quorum.c
index 0bd75450de..cfc1436abb 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -929,7 +929,6 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
                        Error **errp)
 {
     BDRVQuorumState *s = bs->opaque;
-    Error *local_err = NULL;
     QemuOpts *opts = NULL;
     const char *pattern_str;
     bool *opened;
@@ -1007,9 +1006,8 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
 
         s->children[i] = bdrv_open_child(NULL, options, indexstr, bs,
                                          &child_of_bds, BDRV_CHILD_DATA, false,
-                                         &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
+                                         errp);
+        if (!s->children[i]) {
             ret = -EINVAL;
             goto close_exit;
         }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 04/14] blockdev: fix drive_backup_prepare() missed error
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (2 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 05/14] block: drop extra error propagation for bdrv_set_backing_hd Vladimir Sementsov-Ogievskiy
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

We leak local_err and don't report failure to the caller. It's
definitely wrong, let's fix.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 blockdev.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index cd438e60e3..65884a2826 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1825,9 +1825,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
     aio_context_acquire(aio_context);
 
     if (set_backing_hd) {
-        bdrv_set_backing_hd(target_bs, source, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
+        if (bdrv_set_backing_hd(target_bs, source, errp) < 0) {
             goto unref;
         }
     }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 05/14] block: drop extra error propagation for bdrv_set_backing_hd
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (3 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 04/14] blockdev: fix drive_backup_prepare() missed error Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 06/14] block/mirror: drop extra error propagation in commit_active_start() Vladimir Sementsov-Ogievskiy
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

bdrv_set_backing_hd now returns status, let's use it.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/block.c b/block.c
index 48b0de36ff..d679ed8036 100644
--- a/block.c
+++ b/block.c
@@ -2973,11 +2973,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
 
     /* Hook up the backing file link; drop our reference, bs owns the
      * backing_hd reference now */
-    bdrv_set_backing_hd(bs, backing_hd, &local_err);
+    ret = bdrv_set_backing_hd(bs, backing_hd, errp);
     bdrv_unref(backing_hd);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        ret = -EINVAL;
+    if (ret < 0) {
         goto free_exit;
     }
 
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 06/14] block/mirror: drop extra error propagation in commit_active_start()
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (4 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 05/14] block: drop extra error propagation for bdrv_set_backing_hd Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 07/14] blockjob: return status from block_job_set_speed() Vladimir Sementsov-Ogievskiy
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

Let's check return value of mirror_start_job to check for failure
instead of local_err.

Rename ret to job, as ret is usually integer variable.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/mirror.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index fad2701938..b7b5686a57 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1851,8 +1851,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
                               bool auto_complete, Error **errp)
 {
     bool base_read_only;
-    Error *local_err = NULL;
-    BlockJob *ret;
+    BlockJob *job;
 
     base_read_only = bdrv_is_read_only(base);
 
@@ -1862,19 +1861,18 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
         }
     }
 
-    ret = mirror_start_job(
+    job = mirror_start_job(
                      job_id, bs, creation_flags, base, NULL, speed, 0, 0,
                      MIRROR_LEAVE_BACKING_CHAIN, false,
                      on_error, on_error, true, cb, opaque,
                      &commit_active_job_driver, false, base, auto_complete,
                      filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
-                     &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+                     errp);
+    if (!job) {
         goto error_restore_flags;
     }
 
-    return ret;
+    return job;
 
 error_restore_flags:
     /* ignore error and errp for bdrv_reopen, because we want to propagate
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 07/14] blockjob: return status from block_job_set_speed()
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (5 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 06/14] block/mirror: drop extra error propagation in commit_active_start() Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation Vladimir Sementsov-Ogievskiy
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

Better to return status together with setting errp. It allows to avoid
error propagation in the caller.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 include/block/blockjob.h |  2 +-
 blockjob.c               | 18 ++++++++----------
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 35faa3aa26..d200f33c10 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -139,7 +139,7 @@ bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
  * Set a rate-limiting parameter for the job; the actual meaning may
  * vary depending on the job type.
  */
-void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
+bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
 
 /**
  * block_job_query:
diff --git a/blockjob.c b/blockjob.c
index db3a21699c..c96cf7c08a 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -254,18 +254,18 @@ static bool job_timer_pending(Job *job)
     return timer_pending(&job->sleep_timer);
 }
 
-void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
+bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
 {
     const BlockJobDriver *drv = block_job_driver(job);
     int64_t old_speed = job->speed;
 
-    if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp)) {
-        return;
+    if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp) < 0) {
+        return false;
     }
     if (speed < 0) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "speed",
                    "a non-negative value");
-        return;
+        return false;
     }
 
     ratelimit_set_speed(&job->limit, speed, BLOCK_JOB_SLICE_TIME);
@@ -277,11 +277,13 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
     }
 
     if (speed && speed <= old_speed) {
-        return;
+        return true;
     }
 
     /* kick only if a timer is pending */
     job_enter_cond(&job->job, job_timer_pending);
+
+    return true;
 }
 
 int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
@@ -454,12 +456,8 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
 
     /* Only set speed when necessary to avoid NotSupported error */
     if (speed != 0) {
-        Error *local_err = NULL;
-
-        block_job_set_speed(job, speed, &local_err);
-        if (local_err) {
+        if (!block_job_set_speed(job, speed, errp)) {
             job_early_fail(&job->job);
-            error_propagate(errp, local_err);
             return NULL;
         }
     }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (6 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 07/14] blockjob: return status from block_job_set_speed() Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-05 11:43   ` Alberto Garcia
  2021-02-02 12:49 ` [PATCH v7 09/14] block/qcow2-bitmap: improve qcow2_load_dirty_bitmaps() interface Vladimir Sementsov-Ogievskiy
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	stefanha, pbonzini, mreitz, jsnow, ari

Don't use error propagation in qcow2_get_specific_info(). For this
refactor qcow2_get_bitmap_info_list, its current interface is rather
weird.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 block/qcow2.h        |  4 ++--
 block/qcow2-bitmap.c | 26 +++++++++++++-------------
 block/qcow2.c        | 10 +++-------
 3 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 0678073b74..a6bf2881bb 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -979,8 +979,8 @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
                                   void **refcount_table,
                                   int64_t *refcount_table_size);
 bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp);
-Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
-                                                Error **errp);
+bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
+                                Qcow2BitmapInfoList **info_list, Error **errp);
 int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
 int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
 void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 5eef82fa55..c95d6e37e6 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1089,41 +1089,41 @@ static Qcow2BitmapInfoFlagsList *get_bitmap_info_flags(uint32_t flags)
 /*
  * qcow2_get_bitmap_info_list()
  * Returns a list of QCOW2 bitmap details.
- * In case of no bitmaps, the function returns NULL and
- * the @errp parameter is not set.
- * When bitmap information can not be obtained, the function returns
- * NULL and the @errp parameter is set.
+ * On success return true with info_list set (note, that if there are no
+ * bitmaps, info_list is set to NULL).
+ * On failure return false with errp set.
  */
-Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
-                                                Error **errp)
+bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
+                                Qcow2BitmapInfoList **info_list, Error **errp)
 {
     BDRVQcow2State *s = bs->opaque;
     Qcow2BitmapList *bm_list;
     Qcow2Bitmap *bm;
-    Qcow2BitmapInfoList *list = NULL;
-    Qcow2BitmapInfoList **tail = &list;
 
     if (s->nb_bitmaps == 0) {
-        return NULL;
+        *info_list = NULL;
+        return true;
     }
 
     bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
                                s->bitmap_directory_size, errp);
-    if (bm_list == NULL) {
-        return NULL;
+    if (!bm_list) {
+        return false;
     }
 
+    *info_list = NULL;
+
     QSIMPLEQ_FOREACH(bm, bm_list, entry) {
         Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1);
         info->granularity = 1U << bm->granularity_bits;
         info->name = g_strdup(bm->name);
         info->flags = get_bitmap_info_flags(bm->flags & ~BME_RESERVED_FLAGS);
-        QAPI_LIST_APPEND(tail, info);
+        QAPI_LIST_APPEND(info_list, info);
     }
 
     bitmap_list_free(bm_list);
 
-    return list;
+    return true;
 }
 
 int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp)
diff --git a/block/qcow2.c b/block/qcow2.c
index e8dd42d73b..1e83c6cebe 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5063,12 +5063,10 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
     BDRVQcow2State *s = bs->opaque;
     ImageInfoSpecific *spec_info;
     QCryptoBlockInfo *encrypt_info = NULL;
-    Error *local_err = NULL;
 
     if (s->crypto != NULL) {
-        encrypt_info = qcrypto_block_get_info(s->crypto, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
+        encrypt_info = qcrypto_block_get_info(s->crypto, errp);
+        if (!encrypt_info) {
             return NULL;
         }
     }
@@ -5085,9 +5083,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
         };
     } else if (s->qcow_version == 3) {
         Qcow2BitmapInfoList *bitmaps;
-        bitmaps = qcow2_get_bitmap_info_list(bs, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
+        if (!qcow2_get_bitmap_info_list(bs, &bitmaps, errp)) {
             qapi_free_ImageInfoSpecific(spec_info);
             qapi_free_QCryptoBlockInfo(encrypt_info);
             return NULL;
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 09/14] block/qcow2-bitmap: improve qcow2_load_dirty_bitmaps() interface
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (7 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 10/14] block/qcow2-bitmap: return status from qcow2_store_persistent_dirty_bitmaps Vladimir Sementsov-Ogievskiy
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

It's recommended for bool functions with errp to return true on success
and false on failure. Non-standard interfaces don't help to understand
the code. The change is also needed to reduce error propagation.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 block/qcow2.h        |  3 ++-
 block/qcow2-bitmap.c | 26 +++++++++++++++-----------
 block/qcow2.c        |  6 ++----
 3 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index a6bf2881bb..d19c883206 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -978,7 +978,8 @@ void qcow2_cache_discard(Qcow2Cache *c, void *table);
 int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
                                   void **refcount_table,
                                   int64_t *refcount_table_size);
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp);
+bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
+                              Error **errp);
 bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
                                 Qcow2BitmapInfoList **info_list, Error **errp);
 int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index c95d6e37e6..8b28e4c576 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -962,25 +962,27 @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
     bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value);
 }
 
-/* qcow2_load_dirty_bitmaps()
- * Return value is a hint for caller: true means that the Qcow2 header was
- * updated. (false doesn't mean that the header should be updated by the
- * caller, it just means that updating was not needed or the image cannot be
- * written to).
- * On failure the function returns false.
+/*
+ * Return true on success, false on failure.
+ * If header_updated is not NULL then it is set appropriately regardless of
+ * the return value.
  */
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
+bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
+                              Error **errp)
 {
     BDRVQcow2State *s = bs->opaque;
     Qcow2BitmapList *bm_list;
     Qcow2Bitmap *bm;
     GSList *created_dirty_bitmaps = NULL;
-    bool header_updated = false;
     bool needs_update = false;
 
+    if (header_updated) {
+        *header_updated = false;
+    }
+
     if (s->nb_bitmaps == 0) {
         /* No bitmaps - nothing to do */
-        return false;
+        return true;
     }
 
     bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
@@ -1036,7 +1038,9 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
             error_setg_errno(errp, -ret, "Can't update bitmap directory");
             goto fail;
         }
-        header_updated = true;
+        if (header_updated) {
+            *header_updated = true;
+        }
     }
 
     if (!can_write(bs)) {
@@ -1047,7 +1051,7 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
     g_slist_free(created_dirty_bitmaps);
     bitmap_list_free(bm_list);
 
-    return header_updated;
+    return true;
 
 fail:
     g_slist_foreach(created_dirty_bitmaps, release_dirty_bitmap_helper, bs);
diff --git a/block/qcow2.c b/block/qcow2.c
index 1e83c6cebe..20d67bd9c7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1296,7 +1296,6 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
     unsigned int len, i;
     int ret = 0;
     QCowHeader header;
-    Error *local_err = NULL;
     uint64_t ext_end;
     uint64_t l1_vm_state_index;
     bool update_header = false;
@@ -1784,9 +1783,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
 
     if (!(bdrv_get_flags(bs) & BDRV_O_INACTIVE)) {
         /* It's case 1, 2 or 3.2. Or 3.1 which is BUG in management layer. */
-        bool header_updated = qcow2_load_dirty_bitmaps(bs, &local_err);
-        if (local_err != NULL) {
-            error_propagate(errp, local_err);
+        bool header_updated;
+        if (!qcow2_load_dirty_bitmaps(bs, &header_updated, errp)) {
             ret = -EINVAL;
             goto fail;
         }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 10/14] block/qcow2-bitmap: return status from qcow2_store_persistent_dirty_bitmaps
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (8 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 09/14] block/qcow2-bitmap: improve qcow2_load_dirty_bitmaps() interface Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 11/14] block/qcow2: read_cache_sizes: return status value Vladimir Sementsov-Ogievskiy
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

It's better to return status together with setting errp. It makes
possible to avoid error propagation.

While being here, put ERRP_GUARD() to fix error_prepend(errp, ...)
usage inside qcow2_store_persistent_dirty_bitmaps() (see the comment
above ERRP_GUARD() definition in include/qapi/error.h)

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/qcow2.h        |  2 +-
 block/qcow2-bitmap.c | 13 ++++++-------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index d19c883206..0fe5f74ed3 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -984,7 +984,7 @@ bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
                                 Qcow2BitmapInfoList **info_list, Error **errp);
 int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
 int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
-void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
+bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
                                           bool release_stored, Error **errp);
 int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
 bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 8b28e4c576..e50da1ee7d 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1529,9 +1529,10 @@ out:
  * readonly to begin with, and whether we opened directly or reopened to that
  * state shouldn't matter for the state we get afterward.
  */
-void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
+bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
                                           bool release_stored, Error **errp)
 {
+    ERRP_GUARD();
     BdrvDirtyBitmap *bitmap;
     BDRVQcow2State *s = bs->opaque;
     uint32_t new_nb_bitmaps = s->nb_bitmaps;
@@ -1551,7 +1552,7 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
         bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
                                    s->bitmap_directory_size, errp);
         if (bm_list == NULL) {
-            return;
+            return false;
         }
     }
 
@@ -1666,7 +1667,7 @@ success:
     }
 
     bitmap_list_free(bm_list);
-    return;
+    return true;
 
 fail:
     QSIMPLEQ_FOREACH(bm, bm_list, entry) {
@@ -1684,16 +1685,14 @@ fail:
     }
 
     bitmap_list_free(bm_list);
+    return false;
 }
 
 int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp)
 {
     BdrvDirtyBitmap *bitmap;
-    Error *local_err = NULL;
 
-    qcow2_store_persistent_dirty_bitmaps(bs, false, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
+    if (!qcow2_store_persistent_dirty_bitmaps(bs, false, errp)) {
         return -EINVAL;
     }
 
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 11/14] block/qcow2: read_cache_sizes: return status value
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (9 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 10/14] block/qcow2-bitmap: return status from qcow2_store_persistent_dirty_bitmaps Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 12/14] block/qcow2: simplify qcow2_co_invalidate_cache() Vladimir Sementsov-Ogievskiy
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

It's better to return status together with setting errp. It allows to
reduce error propagation.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/qcow2.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 20d67bd9c7..2e0e050997 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -868,7 +868,7 @@ static void qcow2_attach_aio_context(BlockDriverState *bs,
     cache_clean_timer_init(bs, new_context);
 }
 
-static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
+static bool read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
                              uint64_t *l2_cache_size,
                              uint64_t *l2_cache_entry_size,
                              uint64_t *refcount_cache_size, Error **errp)
@@ -906,16 +906,16 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
             error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
                        " and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
                        "at the same time");
-            return;
+            return false;
         } else if (l2_cache_size_set &&
                    (l2_cache_max_setting > combined_cache_size)) {
             error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
                        QCOW2_OPT_CACHE_SIZE);
-            return;
+            return false;
         } else if (*refcount_cache_size > combined_cache_size) {
             error_setg(errp, QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not exceed "
                        QCOW2_OPT_CACHE_SIZE);
-            return;
+            return false;
         }
 
         if (l2_cache_size_set) {
@@ -954,8 +954,10 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
         error_setg(errp, "L2 cache entry size must be a power of two "
                    "between %d and the cluster size (%d)",
                    1 << MIN_CLUSTER_BITS, s->cluster_size);
-        return;
+        return false;
     }
+
+    return true;
 }
 
 typedef struct Qcow2ReopenState {
@@ -982,7 +984,6 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
     int i;
     const char *encryptfmt;
     QDict *encryptopts = NULL;
-    Error *local_err = NULL;
     int ret;
 
     qdict_extract_subqdict(options, &encryptopts, "encrypt.");
@@ -995,10 +996,8 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
     }
 
     /* get L2 table/refcount block cache size from command line options */
-    read_cache_sizes(bs, opts, &l2_cache_size, &l2_cache_entry_size,
-                     &refcount_cache_size, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    if (!read_cache_sizes(bs, opts, &l2_cache_size, &l2_cache_entry_size,
+                          &refcount_cache_size, errp)) {
         ret = -EINVAL;
         goto fail;
     }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 12/14] block/qcow2: simplify qcow2_co_invalidate_cache()
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (10 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 11/14] block/qcow2: read_cache_sizes: return status value Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 13/14] block/qed: bdrv_qed_do_open: deal with errp Vladimir Sementsov-Ogievskiy
  2021-02-02 12:49 ` [PATCH v7 14/14] block/qcow2: refactor qcow2_update_options_prepare error paths Vladimir Sementsov-Ogievskiy
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

qcow2_do_open correctly sets errp on each failure path. So, we can
simplify code in qcow2_co_invalidate_cache() and drop explicit error
propagation.

Add ERRP_GUARD() as mandated by the documentation in
include/qapi/error.h so that error_prepend() is actually called even if
errp is &error_fatal.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 block/qcow2.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 2e0e050997..436bcf0a97 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2715,11 +2715,11 @@ static void qcow2_close(BlockDriverState *bs)
 static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
                                                    Error **errp)
 {
+    ERRP_GUARD();
     BDRVQcow2State *s = bs->opaque;
     int flags = s->flags;
     QCryptoBlock *crypto = NULL;
     QDict *options;
-    Error *local_err = NULL;
     int ret;
 
     /*
@@ -2737,16 +2737,11 @@ static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
 
     flags &= ~BDRV_O_INACTIVE;
     qemu_co_mutex_lock(&s->lock);
-    ret = qcow2_do_open(bs, options, flags, &local_err);
+    ret = qcow2_do_open(bs, options, flags, errp);
     qemu_co_mutex_unlock(&s->lock);
     qobject_unref(options);
-    if (local_err) {
-        error_propagate_prepend(errp, local_err,
-                                "Could not reopen qcow2 layer: ");
-        bs->drv = NULL;
-        return;
-    } else if (ret < 0) {
-        error_setg_errno(errp, -ret, "Could not reopen qcow2 layer");
+    if (ret < 0) {
+        error_prepend(errp, "Could not reopen qcow2 layer: ");
         bs->drv = NULL;
         return;
     }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 13/14] block/qed: bdrv_qed_do_open: deal with errp
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (11 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 12/14] block/qcow2: simplify qcow2_co_invalidate_cache() Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  2021-02-12 22:18   ` Eric Blake
  2021-02-02 12:49 ` [PATCH v7 14/14] block/qcow2: refactor qcow2_update_options_prepare error paths Vladimir Sementsov-Ogievskiy
  13 siblings, 1 reply; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	Greg Kurz, stefanha, pbonzini, mreitz, jsnow, ari

Set errp always on failure. Generic bdrv_open_driver supports driver
functions which can return negative value and forget to set errp.
That's a strange thing.. Let's improve bdrv_qed_do_open to not behave
this way. This allows to simplify code in
bdrv_qed_co_invalidate_cache().

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 block/qed.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/block/qed.c b/block/qed.c
index b27e7546ca..f45c640513 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -393,6 +393,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
 
     ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));
     if (ret < 0) {
+        error_setg(errp, "Failed to read QED header");
         return ret;
     }
     qed_header_le_to_cpu(&le_header, &s->header);
@@ -408,25 +409,30 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
         return -ENOTSUP;
     }
     if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
+        error_setg(errp, "QED cluster size is invalid");
         return -EINVAL;
     }
 
     /* Round down file size to the last cluster */
     file_size = bdrv_getlength(bs->file->bs);
     if (file_size < 0) {
+        error_setg(errp, "Failed to get file length");
         return file_size;
     }
     s->file_size = qed_start_of_cluster(s, file_size);
 
     if (!qed_is_table_size_valid(s->header.table_size)) {
+        error_setg(errp, "QED table size is invalid");
         return -EINVAL;
     }
     if (!qed_is_image_size_valid(s->header.image_size,
                                  s->header.cluster_size,
                                  s->header.table_size)) {
+        error_setg(errp, "QED image size is invalid");
         return -EINVAL;
     }
     if (!qed_check_table_offset(s, s->header.l1_table_offset)) {
+        error_setg(errp, "QED table offset is invalid");
         return -EINVAL;
     }
 
@@ -438,6 +444,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
 
     /* Header size calculation must not overflow uint32_t */
     if (s->header.header_size > UINT32_MAX / s->header.cluster_size) {
+        error_setg(errp, "QED header size is too large");
         return -EINVAL;
     }
 
@@ -445,6 +452,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
         if ((uint64_t)s->header.backing_filename_offset +
             s->header.backing_filename_size >
             s->header.cluster_size * s->header.header_size) {
+            error_setg(errp, "QED backing filename offset is invalid");
             return -EINVAL;
         }
 
@@ -453,6 +461,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
                               bs->auto_backing_file,
                               sizeof(bs->auto_backing_file));
         if (ret < 0) {
+            error_setg(errp, "Failed to read backing filename");
             return ret;
         }
         pstrcpy(bs->backing_file, sizeof(bs->backing_file),
@@ -475,6 +484,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
 
         ret = qed_write_header_sync(s);
         if (ret) {
+            error_setg(errp, "Failed to update header");
             return ret;
         }
 
@@ -487,6 +497,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
 
     ret = qed_read_l1_table_sync(s);
     if (ret) {
+        error_setg(errp, "Failed to read L1 table");
         goto out;
     }
 
@@ -503,6 +514,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
 
             ret = qed_check(s, &result, true);
             if (ret) {
+                error_setg(errp, "Image corrupted");
                 goto out;
             }
         }
@@ -1537,22 +1549,16 @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
                                                       Error **errp)
 {
     BDRVQEDState *s = bs->opaque;
-    Error *local_err = NULL;
     int ret;
 
     bdrv_qed_close(bs);
 
     bdrv_qed_init_state(bs);
     qemu_co_mutex_lock(&s->table_lock);
-    ret = bdrv_qed_do_open(bs, NULL, bs->open_flags, &local_err);
+    ret = bdrv_qed_do_open(bs, NULL, bs->open_flags, errp);
     qemu_co_mutex_unlock(&s->table_lock);
-    if (local_err) {
-        error_propagate_prepend(errp, local_err,
-                                "Could not reopen qed layer: ");
-        return;
-    } else if (ret < 0) {
-        error_setg_errno(errp, -ret, "Could not reopen qed layer");
-        return;
+    if (ret < 0) {
+        error_prepend(errp, "Could not reopen qed layer: ");
     }
 }
 
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v7 14/14] block/qcow2: refactor qcow2_update_options_prepare error paths
  2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
                   ` (12 preceding siblings ...)
  2021-02-02 12:49 ` [PATCH v7 13/14] block/qed: bdrv_qed_do_open: deal with errp Vladimir Sementsov-Ogievskiy
@ 2021-02-02 12:49 ` Vladimir Sementsov-Ogievskiy
  13 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-02 12:49 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, pavel.dovgaluk, qemu-devel, armbru,
	stefanha, pbonzini, mreitz, jsnow, ari

Keep setting ret close to setting errp and don't merge different error
paths into one. This way it's more obvious that we don't return
error without setting errp.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/qcow2.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 436bcf0a97..0aa6ae1e1f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1158,6 +1158,10 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
         }
         qdict_put_str(encryptopts, "format", "qcow");
         r->crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
+        if (!r->crypto_opts) {
+            ret = -EINVAL;
+            goto fail;
+        }
         break;
 
     case QCOW_CRYPT_LUKS:
@@ -1170,14 +1174,15 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
         }
         qdict_put_str(encryptopts, "format", "luks");
         r->crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
+        if (!r->crypto_opts) {
+            ret = -EINVAL;
+            goto fail;
+        }
         break;
 
     default:
         error_setg(errp, "Unsupported encryption method %d",
                    s->crypt_method_header);
-        break;
-    }
-    if (s->crypt_method_header != QCOW_CRYPT_NONE && !r->crypto_opts) {
         ret = -EINVAL;
         goto fail;
     }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 01/14] block: return status from bdrv_append and friends
  2021-02-02 12:49 ` [PATCH v7 01/14] block: return status from bdrv_append and friends Vladimir Sementsov-Ogievskiy
@ 2021-02-05 11:16   ` Alberto Garcia
  2021-02-05 11:26     ` Vladimir Sementsov-Ogievskiy
  0 siblings, 1 reply; 27+ messages in thread
From: Alberto Garcia @ 2021-02-05 11:16 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-block
  Cc: kwolf, vsementsov, pavel.dovgaluk, qemu-devel, armbru, stefanha,
	pbonzini, mreitz, jsnow, ari

On Tue 02 Feb 2021 01:49:43 PM CET, Vladimir Sementsov-Ogievskiy wrote:
> The recommended use of qemu error api assumes returning status together
> with setting errp and avoid void functions with errp parameter. Let's
> improve bdrv_append and some friends to reduce error-propagation
> overhead in further patches.
>
> Choose int return status, because bdrv_replace_node_common() has call
> to bdrv_check_update_perm(), which reports int status, which seems
> correct to propagate.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

I had already reviewed this one, hadn't I?

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 01/14] block: return status from bdrv_append and friends
  2021-02-05 11:16   ` Alberto Garcia
@ 2021-02-05 11:26     ` Vladimir Sementsov-Ogievskiy
  0 siblings, 0 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-05 11:26 UTC (permalink / raw)
  To: Alberto Garcia, qemu-block
  Cc: qemu-devel, armbru, eblake, jsnow, stefanha, pbonzini,
	pavel.dovgaluk, ari, mreitz, kwolf

05.02.2021 14:16, Alberto Garcia wrote:
> On Tue 02 Feb 2021 01:49:43 PM CET, Vladimir Sementsov-Ogievskiy wrote:
>> The recommended use of qemu error api assumes returning status together
>> with setting errp and avoid void functions with errp parameter. Let's
>> improve bdrv_append and some friends to reduce error-propagation
>> overhead in further patches.
>>
>> Choose int return status, because bdrv_replace_node_common() has call
>> to bdrv_check_update_perm(), which reports int status, which seems
>> correct to propagate.
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> 
> I had already reviewed this one, hadn't I?
> 
> Reviewed-by: Alberto Garcia <berto@igalia.com>

Oh right, sorry.

-- 
Best regards,
Vladimir


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation
  2021-02-02 12:49 ` [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation Vladimir Sementsov-Ogievskiy
@ 2021-02-05 11:43   ` Alberto Garcia
  2021-02-05 11:52     ` Vladimir Sementsov-Ogievskiy
  0 siblings, 1 reply; 27+ messages in thread
From: Alberto Garcia @ 2021-02-05 11:43 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-block
  Cc: kwolf, vsementsov, pavel.dovgaluk, qemu-devel, armbru, stefanha,
	pbonzini, mreitz, jsnow, ari

On Tue 02 Feb 2021 01:49:50 PM CET, Vladimir Sementsov-Ogievskiy wrote:
> -Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
> -                                                Error **errp)
> +bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
> +                                Qcow2BitmapInfoList **info_list, Error **errp)
>  {
>      BDRVQcow2State *s = bs->opaque;
>      Qcow2BitmapList *bm_list;
>      Qcow2Bitmap *bm;
> -    Qcow2BitmapInfoList *list = NULL;
> -    Qcow2BitmapInfoList **tail = &list;
>  
>      if (s->nb_bitmaps == 0) {
> -        return NULL;
> +        *info_list = NULL;
> +        return true;
>      }
>  
>      bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
>                                 s->bitmap_directory_size, errp);
> -    if (bm_list == NULL) {
> -        return NULL;
> +    if (!bm_list) {
> +        return false;
>      }
>  
> +    *info_list = NULL;
> +
>      QSIMPLEQ_FOREACH(bm, bm_list, entry) {
>          Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1);
>          info->granularity = 1U << bm->granularity_bits;
>          info->name = g_strdup(bm->name);
>          info->flags = get_bitmap_info_flags(bm->flags & ~BME_RESERVED_FLAGS);
> -        QAPI_LIST_APPEND(tail, info);
> +        QAPI_LIST_APPEND(info_list, info);
>      }
>  
>      bitmap_list_free(bm_list);
>  
> -    return list;
> +    return true;
>  }

Maybe I'm reading this wrong but...

In the original code you had the head and tail of the list ('list' and
'tail') then you would append items to the tail and finally return the
head.

However the new code only uses and updates 'info_list' and it does not
keep the head anywhere, so what the caller gets is a pointer to the
tail.

Berto


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation
  2021-02-05 11:43   ` Alberto Garcia
@ 2021-02-05 11:52     ` Vladimir Sementsov-Ogievskiy
  2021-02-05 12:01       ` Alberto Garcia
  2021-02-12 19:44       ` Eric Blake
  0 siblings, 2 replies; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-05 11:52 UTC (permalink / raw)
  To: Alberto Garcia, qemu-block
  Cc: qemu-devel, armbru, eblake, jsnow, stefanha, pbonzini,
	pavel.dovgaluk, ari, mreitz, kwolf

05.02.2021 14:43, Alberto Garcia wrote:
> On Tue 02 Feb 2021 01:49:50 PM CET, Vladimir Sementsov-Ogievskiy wrote:
>> -Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
>> -                                                Error **errp)
>> +bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
>> +                                Qcow2BitmapInfoList **info_list, Error **errp)
>>   {
>>       BDRVQcow2State *s = bs->opaque;
>>       Qcow2BitmapList *bm_list;
>>       Qcow2Bitmap *bm;
>> -    Qcow2BitmapInfoList *list = NULL;
>> -    Qcow2BitmapInfoList **tail = &list;
>>   
>>       if (s->nb_bitmaps == 0) {
>> -        return NULL;
>> +        *info_list = NULL;
>> +        return true;
>>       }
>>   
>>       bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
>>                                  s->bitmap_directory_size, errp);
>> -    if (bm_list == NULL) {
>> -        return NULL;
>> +    if (!bm_list) {
>> +        return false;
>>       }
>>   
>> +    *info_list = NULL;
>> +
>>       QSIMPLEQ_FOREACH(bm, bm_list, entry) {
>>           Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1);
>>           info->granularity = 1U << bm->granularity_bits;
>>           info->name = g_strdup(bm->name);
>>           info->flags = get_bitmap_info_flags(bm->flags & ~BME_RESERVED_FLAGS);
>> -        QAPI_LIST_APPEND(tail, info);
>> +        QAPI_LIST_APPEND(info_list, info);
>>       }
>>   
>>       bitmap_list_free(bm_list);
>>   
>> -    return list;
>> +    return true;
>>   }
> 
> Maybe I'm reading this wrong but...
> 
> In the original code you had the head and tail of the list ('list' and
> 'tail') then you would append items to the tail and finally return the
> head.
> 
> However the new code only uses and updates 'info_list' and it does not
> keep the head anywhere, so what the caller gets is a pointer to the
> tail.
> 

No. *info_list is modified only on the first loop iteration. And than info_list is switched to &(*(info_list))->next, so on second iteration we will modify @next field of first element, not original *info_list.



-- 
Best regards,
Vladimir


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation
  2021-02-05 11:52     ` Vladimir Sementsov-Ogievskiy
@ 2021-02-05 12:01       ` Alberto Garcia
  2021-02-12 19:44       ` Eric Blake
  1 sibling, 0 replies; 27+ messages in thread
From: Alberto Garcia @ 2021-02-05 12:01 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-block
  Cc: kwolf, pavel.dovgaluk, qemu-devel, armbru, stefanha, pbonzini,
	mreitz, jsnow, ari

On Fri 05 Feb 2021 12:52:03 PM CET, Vladimir Sementsov-Ogievskiy wrote:
>> However the new code only uses and updates 'info_list' and it does not
>> keep the head anywhere, so what the caller gets is a pointer to the
>> tail.
>> 
>
> No. *info_list is modified only on the first loop iteration. And than
> info_list is switched to &(*(info_list))->next, so on second iteration
> we will modify @next field of first element, not original *info_list.

Right, I see!

I find it a bit confusing, 'info_list' is at the same time a return
value and a local variable that you use to iterate over the list.

Anyway,

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation
  2021-02-05 11:52     ` Vladimir Sementsov-Ogievskiy
  2021-02-05 12:01       ` Alberto Garcia
@ 2021-02-12 19:44       ` Eric Blake
  1 sibling, 0 replies; 27+ messages in thread
From: Eric Blake @ 2021-02-12 19:44 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, Alberto Garcia, qemu-block
  Cc: kwolf, stefanha, qemu-devel, armbru, pavel.dovgaluk, pbonzini,
	mreitz, jsnow, ari

On 2/5/21 5:52 AM, Vladimir Sementsov-Ogievskiy wrote:
> 05.02.2021 14:43, Alberto Garcia wrote:
>> On Tue 02 Feb 2021 01:49:50 PM CET, Vladimir Sementsov-Ogievskiy wrote:
>>> -Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
>>> -                                                Error **errp)
>>> +bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
>>> +                                Qcow2BitmapInfoList **info_list,
>>> Error **errp)
>>>   {
>>>       BDRVQcow2State *s = bs->opaque;
>>>       Qcow2BitmapList *bm_list;
>>>       Qcow2Bitmap *bm;
>>> -    Qcow2BitmapInfoList *list = NULL;
>>> -    Qcow2BitmapInfoList **tail = &list;
>>>         if (s->nb_bitmaps == 0) {
>>> -        return NULL;
>>> +        *info_list = NULL;
>>> +        return true;
>>>       }
>>>         bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
>>>                                  s->bitmap_directory_size, errp);
>>> -    if (bm_list == NULL) {
>>> -        return NULL;
>>> +    if (!bm_list) {
>>> +        return false;
>>>       }
>>>   +    *info_list = NULL;
>>> +
>>>       QSIMPLEQ_FOREACH(bm, bm_list, entry) {
>>>           Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1);
>>>           info->granularity = 1U << bm->granularity_bits;
>>>           info->name = g_strdup(bm->name);
>>>           info->flags = get_bitmap_info_flags(bm->flags &
>>> ~BME_RESERVED_FLAGS);
>>> -        QAPI_LIST_APPEND(tail, info);
>>> +        QAPI_LIST_APPEND(info_list, info);
>>>       }
>>>         bitmap_list_free(bm_list);
>>>   -    return list;
>>> +    return true;
>>>   }
>>
>> Maybe I'm reading this wrong but...
>>
>> In the original code you had the head and tail of the list ('list' and
>> 'tail') then you would append items to the tail and finally return the
>> head.
>>
>> However the new code only uses and updates 'info_list' and it does not
>> keep the head anywhere, so what the caller gets is a pointer to the
>> tail.
>>
> 
> No. *info_list is modified only on the first loop iteration. And than
> info_list is switched to &(*(info_list))->next, so on second iteration
> we will modify @next field of first element, not original *info_list.

Elsewhere when making these types of conversions, Markus suggested that
I keep a separate tail variable, initialized by the parameter info_list,
to make it more apparent.  As in squashing the patch below:

With that, it looks this series is reviewed, so I'm planning on taking
it through my dirty-bitmaps tree (perhaps I'm stretching the fact that
patch 10/14 is definitely dirty-bitmaps into taking the whole series,
but I doubt I'll hear any complaints from other block maintainers)


diff --git i/block/qcow2-bitmap.c w/block/qcow2-bitmap.c
index e50da1ee7da3..f417f9ccb195 100644
--- i/block/qcow2-bitmap.c
+++ w/block/qcow2-bitmap.c
@@ -1103,6 +1103,7 @@ bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
     BDRVQcow2State *s = bs->opaque;
     Qcow2BitmapList *bm_list;
     Qcow2Bitmap *bm;
+    Qcow2BitmapInfoList **tail;

     if (s->nb_bitmaps == 0) {
         *info_list = NULL;
@@ -1116,13 +1117,14 @@ bool qcow2_get_bitmap_info_list(BlockDriverState
*bs,
     }

     *info_list = NULL;
+    tail = info_list;

     QSIMPLEQ_FOREACH(bm, bm_list, entry) {
         Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1);
         info->granularity = 1U << bm->granularity_bits;
         info->name = g_strdup(bm->name);
         info->flags = get_bitmap_info_flags(bm->flags &
~BME_RESERVED_FLAGS);
-        QAPI_LIST_APPEND(info_list, info);
+        QAPI_LIST_APPEND(tail, info);
     }

     bitmap_list_free(bm_list);

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 13/14] block/qed: bdrv_qed_do_open: deal with errp
  2021-02-02 12:49 ` [PATCH v7 13/14] block/qed: bdrv_qed_do_open: deal with errp Vladimir Sementsov-Ogievskiy
@ 2021-02-12 22:18   ` Eric Blake
  0 siblings, 0 replies; 27+ messages in thread
From: Eric Blake @ 2021-02-12 22:18 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-block
  Cc: kwolf, berto, pavel.dovgaluk, qemu-devel, armbru, Greg Kurz,
	stefanha, pbonzini, mreitz, jsnow, ari

On 2/2/21 6:49 AM, Vladimir Sementsov-Ogievskiy wrote:
> Set errp always on failure. Generic bdrv_open_driver supports driver
> functions which can return negative value and forget to set errp.
> That's a strange thing.. Let's improve bdrv_qed_do_open to not behave
> this way. This allows to simplify code in
> bdrv_qed_co_invalidate_cache().

Grammar tweak:

Always set errp on failure.  Generic bdrv_open_driver supports driver
functions which can return a negative value but forget to set errp.
That's a strange thing. Let's improve bdrv_qed_do_open to not behave
this way.  This allows the simplification of code in
bdrv_qed_co_invalidate_cache().

> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> Reviewed-by: Alberto Garcia <berto@igalia.com>
> Reviewed-by: Greg Kurz <groug@kaod.org>
> ---
>  block/qed.c | 24 +++++++++++++++---------
>  1 file changed, 15 insertions(+), 9 deletions(-)
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation
  2021-02-02 12:49 ` [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation Vladimir Sementsov-Ogievskiy
@ 2021-02-12 23:13   ` Eric Blake
  2021-02-15  9:22     ` Kevin Wolf
  0 siblings, 1 reply; 27+ messages in thread
From: Eric Blake @ 2021-02-12 23:13 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-block
  Cc: kwolf, berto, pavel.dovgaluk, qemu-devel, armbru, Greg Kurz,
	stefanha, pbonzini, mreitz, jsnow, ari

On 2/2/21 6:49 AM, Vladimir Sementsov-Ogievskiy wrote:
> This patch is generated by cocci script:
> 
> @@
> symbol bdrv_open_child, errp, local_err;
> expression file;
> @@
> 
>   file = bdrv_open_child(...,
> -                        &local_err
> +                        errp
>                         );
> - if (local_err)
> + if (!file)
>   {
>       ...
> -     error_propagate(errp, local_err);
>       ...
>   }
> 
> with command
> 
> spatch --sp-file x.cocci --macro-file scripts/cocci-macro-file.h \
> --in-place --no-show-diff --max-width 80 --use-gitgrep block

With this patch applied, 'check unit-test' fails with:

Running test test-replication
Unexpected error in bdrv_open_driver() at ../block.c:1481:
Could not open '/tmp/p_local_disk.z1Ugyc': Invalid argument
ERROR test-replication - missing test plan

Directly reverting it has ripple effect on later patches in the series.

Running test-replication under gdb gives this backtrace:

Thread 1 "test-replicatio" received signal SIGABRT, Aborted.
0x00007ffff6f6f9d5 in raise () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff6f6f9d5 in raise () from /lib64/libc.so.6
#1  0x00007ffff6f588a4 in abort () from /lib64/libc.so.6
#2  0x00005555556ad820 in error_handle_fatal (
    errp=0x555555790568 <error_abort>, err=0x555555859010)
    at ../util/error.c:40
#3  0x00005555556ae3cf in error_propagate (
    dst_errp=0x555555790568 <error_abort>, local_err=0x555555859010)
    at ../util/error.c:286
#4  0x000055555558cc9e in bdrv_img_create (
    filename=0x555555822500 "/tmp/p_local_disk.DVFoWt",
    fmt=0x5555556e809a "qcow2", base_filename=0x0, base_fmt=0x0,
options=0x0,
    img_size=67108864, flags=2, quiet=true, errp=0x555555790568
<error_abort>)
    at ../block.c:6312

> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> Reviewed-by: Greg Kurz <groug@kaod.org>
> Reviewed-by: Alberto Garcia <berto@igalia.com>
> ---
>  block/blkdebug.c     |  6 ++----
>  block/blklogwrites.c | 10 ++++------
>  block/blkreplay.c    |  6 ++----
>  block/blkverify.c    | 11 ++++-------
>  block/qcow2.c        |  5 ++---
>  block/quorum.c       |  6 ++----
>  6 files changed, 16 insertions(+), 28 deletions(-)

And this diffstat doesn't immediately tell me what ended up violating
the assumptions of error_abort.  As such, at this point I'm temporarily
dropping the remainder of the series from my bitmaps queue, and only
including patches 1 and 2 in my next pull request.  Looking forward to v8.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation
  2021-02-12 23:13   ` Eric Blake
@ 2021-02-15  9:22     ` Kevin Wolf
  2021-02-15 20:04       ` Eric Blake
  0 siblings, 1 reply; 27+ messages in thread
From: Kevin Wolf @ 2021-02-15  9:22 UTC (permalink / raw)
  To: Eric Blake
  Cc: Vladimir Sementsov-Ogievskiy, berto, pavel.dovgaluk, qemu-block,
	qemu-devel, armbru, Greg Kurz, stefanha, pbonzini, mreitz, jsnow,
	ari

Am 13.02.2021 um 00:13 hat Eric Blake geschrieben:
> On 2/2/21 6:49 AM, Vladimir Sementsov-Ogievskiy wrote:
> > This patch is generated by cocci script:
> > 
> > @@
> > symbol bdrv_open_child, errp, local_err;
> > expression file;
> > @@
> > 
> >   file = bdrv_open_child(...,
> > -                        &local_err
> > +                        errp
> >                         );
> > - if (local_err)
> > + if (!file)
> >   {
> >       ...
> > -     error_propagate(errp, local_err);
> >       ...
> >   }
> > 
> > with command
> > 
> > spatch --sp-file x.cocci --macro-file scripts/cocci-macro-file.h \
> > --in-place --no-show-diff --max-width 80 --use-gitgrep block
> 
> With this patch applied, 'check unit-test' fails with:
> 
> Running test test-replication
> Unexpected error in bdrv_open_driver() at ../block.c:1481:
> Could not open '/tmp/p_local_disk.z1Ugyc': Invalid argument
> ERROR test-replication - missing test plan
> 
> Directly reverting it has ripple effect on later patches in the series.
> 
> Running test-replication under gdb gives this backtrace:
> 
> Thread 1 "test-replicatio" received signal SIGABRT, Aborted.
> 0x00007ffff6f6f9d5 in raise () from /lib64/libc.so.6
> (gdb) bt
> #0  0x00007ffff6f6f9d5 in raise () from /lib64/libc.so.6
> #1  0x00007ffff6f588a4 in abort () from /lib64/libc.so.6
> #2  0x00005555556ad820 in error_handle_fatal (
>     errp=0x555555790568 <error_abort>, err=0x555555859010)
>     at ../util/error.c:40
> #3  0x00005555556ae3cf in error_propagate (
>     dst_errp=0x555555790568 <error_abort>, local_err=0x555555859010)
>     at ../util/error.c:286
> #4  0x000055555558cc9e in bdrv_img_create (
>     filename=0x555555822500 "/tmp/p_local_disk.DVFoWt",
>     fmt=0x5555556e809a "qcow2", base_filename=0x0, base_fmt=0x0,
> options=0x0,
>     img_size=67108864, flags=2, quiet=true, errp=0x555555790568
> <error_abort>)
>     at ../block.c:6312

The problem is this hunk:

diff --git a/block/qcow2.c b/block/qcow2.c
index 5d94f45be9..e8dd42d73b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1611,9 +1611,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
     /* Open external data file */
     s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
                                    &child_of_bds, BDRV_CHILD_DATA,
-                                   true, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+                                   true, errp);
+    if (!s->data_file) {
         ret = -EINVAL;
         goto fail;
     }

bdrv_open_child() can return NULL in non-error cases, when the child is
optional and it isn't given. The test doesn't use an external data file,
so this returns NULL without setting an error, which now gets turned
into -EINVAL instead.

This makes the most basic tests fail with qcow2 (iotests 001 is enough).

The other hunks in this patch don't suffer from the same problem because
they pass allow_none=false.

Kevin



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation
  2021-02-15  9:22     ` Kevin Wolf
@ 2021-02-15 20:04       ` Eric Blake
  2021-02-16  5:03         ` Vladimir Sementsov-Ogievskiy
  0 siblings, 1 reply; 27+ messages in thread
From: Eric Blake @ 2021-02-15 20:04 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: Vladimir Sementsov-Ogievskiy, berto, pavel.dovgaluk, qemu-block,
	qemu-devel, armbru, Greg Kurz, stefanha, pbonzini, mreitz, jsnow,
	ari

On 2/15/21 3:22 AM, Kevin Wolf wrote:

>> With this patch applied, 'check unit-test' fails with:
>>
>> Running test test-replication
>> Unexpected error in bdrv_open_driver() at ../block.c:1481:
>> Could not open '/tmp/p_local_disk.z1Ugyc': Invalid argument
>> ERROR test-replication - missing test plan
>>

> The problem is this hunk:
> 
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 5d94f45be9..e8dd42d73b 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -1611,9 +1611,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
>      /* Open external data file */
>      s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
>                                     &child_of_bds, BDRV_CHILD_DATA,
> -                                   true, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> +                                   true, errp);
> +    if (!s->data_file) {
>          ret = -EINVAL;
>          goto fail;
>      }
> 
> bdrv_open_child() can return NULL in non-error cases, when the child is
> optional and it isn't given. The test doesn't use an external data file,
> so this returns NULL without setting an error, which now gets turned
> into -EINVAL instead.
> 
> This makes the most basic tests fail with qcow2 (iotests 001 is enough).
> 
> The other hunks in this patch don't suffer from the same problem because
> they pass allow_none=false.

Thanks; that's enough to figure out how to repair the patch:

diff --git i/block/qcow2.c w/block/qcow2.c
index e8dd42d73b4c..38137ca30eb0 100644
--- i/block/qcow2.c
+++ w/block/qcow2.c
@@ -1292,6 +1292,7 @@ static int
validate_compression_type(BDRVQcow2State *s, Error **errp)
 static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
                                       int flags, Error **errp)
 {
+    ERRP_GUARD();
     BDRVQcow2State *s = bs->opaque;
     unsigned int len, i;
     int ret = 0;
@@ -1612,7 +1613,7 @@ static int coroutine_fn
qcow2_do_open(BlockDriverState *bs, QDict *options,
     s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
                                    &child_of_bds, BDRV_CHILD_DATA,
                                    true, errp);
-    if (!s->data_file) {
+    if (*errp) {
         ret = -EINVAL;
         goto fail;
     }


-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation
  2021-02-15 20:04       ` Eric Blake
@ 2021-02-16  5:03         ` Vladimir Sementsov-Ogievskiy
  2021-02-16  9:02           ` Kevin Wolf
  0 siblings, 1 reply; 27+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2021-02-16  5:03 UTC (permalink / raw)
  To: Eric Blake, Kevin Wolf
  Cc: qemu-block, qemu-devel, armbru, berto, jsnow, stefanha, pbonzini,
	pavel.dovgaluk, ari, mreitz, Greg Kurz

15.02.2021 23:04, Eric Blake wrote:
> On 2/15/21 3:22 AM, Kevin Wolf wrote:
> 
>>> With this patch applied, 'check unit-test' fails with:
>>>
>>> Running test test-replication
>>> Unexpected error in bdrv_open_driver() at ../block.c:1481:
>>> Could not open '/tmp/p_local_disk.z1Ugyc': Invalid argument
>>> ERROR test-replication - missing test plan
>>>
> 
>> The problem is this hunk:
>>
>> diff --git a/block/qcow2.c b/block/qcow2.c
>> index 5d94f45be9..e8dd42d73b 100644
>> --- a/block/qcow2.c
>> +++ b/block/qcow2.c
>> @@ -1611,9 +1611,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
>>       /* Open external data file */
>>       s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
>>                                      &child_of_bds, BDRV_CHILD_DATA,
>> -                                   true, &local_err);
>> -    if (local_err) {
>> -        error_propagate(errp, local_err);
>> +                                   true, errp);
>> +    if (!s->data_file) {
>>           ret = -EINVAL;
>>           goto fail;
>>       }
>>
>> bdrv_open_child() can return NULL in non-error cases, when the child is
>> optional and it isn't given. The test doesn't use an external data file,
>> so this returns NULL without setting an error, which now gets turned
>> into -EINVAL instead.
>>
>> This makes the most basic tests fail with qcow2 (iotests 001 is enough).
>>
>> The other hunks in this patch don't suffer from the same problem because
>> they pass allow_none=false.
> 
> Thanks; that's enough to figure out how to repair the patch:
> 
> diff --git i/block/qcow2.c w/block/qcow2.c
> index e8dd42d73b4c..38137ca30eb0 100644
> --- i/block/qcow2.c
> +++ w/block/qcow2.c
> @@ -1292,6 +1292,7 @@ static int
> validate_compression_type(BDRVQcow2State *s, Error **errp)
>   static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
>                                         int flags, Error **errp)
>   {
> +    ERRP_GUARD();
>       BDRVQcow2State *s = bs->opaque;
>       unsigned int len, i;
>       int ret = 0;
> @@ -1612,7 +1613,7 @@ static int coroutine_fn
> qcow2_do_open(BlockDriverState *bs, QDict *options,
>       s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
>                                      &child_of_bds, BDRV_CHILD_DATA,
>                                      true, errp);
> -    if (!s->data_file) {
> +    if (*errp) {
>           ret = -EINVAL;
>           goto fail;
>       }
> 
> 

Agree.. Or better refactor bdrv_open_child to follow more common (and recommended) semantics (i.e. NULL + errp on error, non-null on succsess).. But this will require more investigation.

I'm busy now with our internal deadline (this week), after this will return to handle upstream things.

-- 
Best regards,
Vladimir


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation
  2021-02-16  5:03         ` Vladimir Sementsov-Ogievskiy
@ 2021-02-16  9:02           ` Kevin Wolf
  0 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2021-02-16  9:02 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy
  Cc: berto, pavel.dovgaluk, qemu-block, qemu-devel, armbru, Greg Kurz,
	stefanha, pbonzini, mreitz, jsnow, ari

Am 16.02.2021 um 06:03 hat Vladimir Sementsov-Ogievskiy geschrieben:
> 15.02.2021 23:04, Eric Blake wrote:
> > On 2/15/21 3:22 AM, Kevin Wolf wrote:
> > 
> > > > With this patch applied, 'check unit-test' fails with:
> > > > 
> > > > Running test test-replication
> > > > Unexpected error in bdrv_open_driver() at ../block.c:1481:
> > > > Could not open '/tmp/p_local_disk.z1Ugyc': Invalid argument
> > > > ERROR test-replication - missing test plan
> > > > 
> > 
> > > The problem is this hunk:
> > > 
> > > diff --git a/block/qcow2.c b/block/qcow2.c
> > > index 5d94f45be9..e8dd42d73b 100644
> > > --- a/block/qcow2.c
> > > +++ b/block/qcow2.c
> > > @@ -1611,9 +1611,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
> > >       /* Open external data file */
> > >       s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
> > >                                      &child_of_bds, BDRV_CHILD_DATA,
> > > -                                   true, &local_err);
> > > -    if (local_err) {
> > > -        error_propagate(errp, local_err);
> > > +                                   true, errp);
> > > +    if (!s->data_file) {
> > >           ret = -EINVAL;
> > >           goto fail;
> > >       }
> > > 
> > > bdrv_open_child() can return NULL in non-error cases, when the child is
> > > optional and it isn't given. The test doesn't use an external data file,
> > > so this returns NULL without setting an error, which now gets turned
> > > into -EINVAL instead.
> > > 
> > > This makes the most basic tests fail with qcow2 (iotests 001 is enough).
> > > 
> > > The other hunks in this patch don't suffer from the same problem because
> > > they pass allow_none=false.
> > 
> > Thanks; that's enough to figure out how to repair the patch:
> > 
> > diff --git i/block/qcow2.c w/block/qcow2.c
> > index e8dd42d73b4c..38137ca30eb0 100644
> > --- i/block/qcow2.c
> > +++ w/block/qcow2.c
> > @@ -1292,6 +1292,7 @@ static int
> > validate_compression_type(BDRVQcow2State *s, Error **errp)
> >   static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
> >                                         int flags, Error **errp)
> >   {
> > +    ERRP_GUARD();
> >       BDRVQcow2State *s = bs->opaque;
> >       unsigned int len, i;
> >       int ret = 0;
> > @@ -1612,7 +1613,7 @@ static int coroutine_fn
> > qcow2_do_open(BlockDriverState *bs, QDict *options,
> >       s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
> >                                      &child_of_bds, BDRV_CHILD_DATA,
> >                                      true, errp);
> > -    if (!s->data_file) {
> > +    if (*errp) {
> >           ret = -EINVAL;
> >           goto fail;
> >       }
> 
> Agree.. Or better refactor bdrv_open_child to follow more common (and
> recommended) semantics (i.e. NULL + errp on error, non-null on
> succsess).. But this will require more investigation.

But what non-NULL value to return when there is no BdrvChild object?

If anything, you could switch to an int return value and pass the
BdrvChild pointer by reference. I'm not sure if that would be a massive
improvement, though.

Kevin



^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2021-02-16  9:03 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-02 12:49 [PATCH v7 00/14] block: deal with errp: part I Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 01/14] block: return status from bdrv_append and friends Vladimir Sementsov-Ogievskiy
2021-02-05 11:16   ` Alberto Garcia
2021-02-05 11:26     ` Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 02/14] block: use return status of bdrv_append() Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 03/14] block: check return value of bdrv_open_child and drop error propagation Vladimir Sementsov-Ogievskiy
2021-02-12 23:13   ` Eric Blake
2021-02-15  9:22     ` Kevin Wolf
2021-02-15 20:04       ` Eric Blake
2021-02-16  5:03         ` Vladimir Sementsov-Ogievskiy
2021-02-16  9:02           ` Kevin Wolf
2021-02-02 12:49 ` [PATCH v7 04/14] blockdev: fix drive_backup_prepare() missed error Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 05/14] block: drop extra error propagation for bdrv_set_backing_hd Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 06/14] block/mirror: drop extra error propagation in commit_active_start() Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 07/14] blockjob: return status from block_job_set_speed() Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 08/14] block/qcow2: qcow2_get_specific_info(): drop error propagation Vladimir Sementsov-Ogievskiy
2021-02-05 11:43   ` Alberto Garcia
2021-02-05 11:52     ` Vladimir Sementsov-Ogievskiy
2021-02-05 12:01       ` Alberto Garcia
2021-02-12 19:44       ` Eric Blake
2021-02-02 12:49 ` [PATCH v7 09/14] block/qcow2-bitmap: improve qcow2_load_dirty_bitmaps() interface Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 10/14] block/qcow2-bitmap: return status from qcow2_store_persistent_dirty_bitmaps Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 11/14] block/qcow2: read_cache_sizes: return status value Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 12/14] block/qcow2: simplify qcow2_co_invalidate_cache() Vladimir Sementsov-Ogievskiy
2021-02-02 12:49 ` [PATCH v7 13/14] block/qed: bdrv_qed_do_open: deal with errp Vladimir Sementsov-Ogievskiy
2021-02-12 22:18   ` Eric Blake
2021-02-02 12:49 ` [PATCH v7 14/14] block/qcow2: refactor qcow2_update_options_prepare error paths Vladimir Sementsov-Ogievskiy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.