diff mbox series

[v5,01/14] block: return status from bdrv_append and friends

Message ID 20210109125811.209870-2-vsementsov@virtuozzo.com (mailing list archive)
State New, archived
Headers show
Series block: deal with errp: part I | expand

Commit Message

Vladimir Sementsov-Ogievskiy Jan. 9, 2021, 12:57 p.m. UTC
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               | 57 ++++++++++++++++++++++++++++---------------
 2 files changed, 43 insertions(+), 26 deletions(-)

Comments

Alberto Garcia Jan. 12, 2021, 5:27 p.m. UTC | #1
On Sat 09 Jan 2021 01:57:58 PM CET, Vladimir Sementsov-Ogievskiy wrote:
> -void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
> +int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
>                           Error **errp)

The indentation of the second line should be adjusted, shouldn't it?

>  {
> +    int ret;
>      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,24 @@ 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;
> +    }

This is not visible in the patch, but before the bdrv_attach_child()
call there's this:

    if (!backing_hd) {
        goto out;
    }

But in this case 'ret' is still uninitialized.

>  out:
>      bdrv_refresh_limits(bs, NULL);
> +
> +    return ret;
>  }



> -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;
> @@ -4562,6 +4572,7 @@ static void bdrv_replace_node_common(BlockDriverState *from,
>              goto out;
>          }
>          if (c->frozen) {
> +            ret = -EPERM;
>              error_setg(errp, "Cannot change '%s' link to '%s'",
>                         c->name, from->node_name);
>              goto out;

Same here, you set 'ret' in the second 'goto out' but not in the first.

Berto
Vladimir Sementsov-Ogievskiy Jan. 13, 2021, 9:59 a.m. UTC | #2
12.01.2021 20:27, Alberto Garcia wrote:
> On Sat 09 Jan 2021 01:57:58 PM CET, Vladimir Sementsov-Ogievskiy wrote:
>> -void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
>> +int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
>>                            Error **errp)
> 
> The indentation of the second line should be adjusted, shouldn't it?
> 
>>   {
>> +    int ret;
>>       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,24 @@ 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;
>> +    }
> 
> This is not visible in the patch, but before the bdrv_attach_child()
> call there's this:
> 
>      if (!backing_hd) {
>          goto out;
>      }
> 
> But in this case 'ret' is still uninitialized.
> 
>>   out:
>>       bdrv_refresh_limits(bs, NULL);
>> +
>> +    return ret;
>>   }
> 
> 
> 
>> -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;
>> @@ -4562,6 +4572,7 @@ static void bdrv_replace_node_common(BlockDriverState *from,
>>               goto out;
>>           }
>>           if (c->frozen) {
>> +            ret = -EPERM;
>>               error_setg(errp, "Cannot change '%s' link to '%s'",
>>                          c->name, from->node_name);
>>               goto out;
> 
> Same here, you set 'ret' in the second 'goto out' but not in the first.
> 
Oops, you are right, thanks!
diff mbox series

Patch

diff --git a/include/block/block.h b/include/block/block.h
index a193545b6a..b4e0347b49 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -354,10 +354,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);
 
 int bdrv_parse_aio(const char *mode, int *flags);
 int bdrv_parse_cache_mode(const char *mode, int *flags, bool *writethrough);
@@ -369,8 +369,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 8b9d457546..1a5d0e748d 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,
+int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
                          Error **errp)
 {
+    int ret;
     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,24 @@  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;
     }
 
+    ret = 0;
+
 out:
     bdrv_refresh_limits(bs, NULL);
+
+    return ret;
 }
 
 /*
@@ -4533,9 +4543,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;
@@ -4562,6 +4572,7 @@  static void bdrv_replace_node_common(BlockDriverState *from,
             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 +4603,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 +4635,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)