[PATCH 7/8] block: improve bdrv_replace_node_noperm()

Vladimir Sementsov-Ogievskiy vsementsov at virtuozzo.com
Mon Aug 2 18:54:15 UTC 2021


Add optional block edge name filter and new mode: "exactly one", which
we are going to use soon.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov at virtuozzo.com>
---
 block.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/block.c b/block.c
index 449f933661..ae8c8c4032 100644
--- a/block.c
+++ b/block.c
@@ -4894,13 +4894,22 @@ static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
 
 static int bdrv_replace_node_noperm(BlockDriverState *from,
                                     BlockDriverState *to,
-                                    bool auto_skip, Transaction *tran,
+                                    bool auto_skip,
+                                    const char *edge_name,
+                                    bool exactly_one,
+                                    Transaction *tran,
                                     Error **errp)
 {
     BdrvChild *c, *next;
+    bool found = false;
+
+    assert(!(auto_skip && exactly_one));
 
     QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
         assert(c->bs == from);
+        if (edge_name && strcmp(edge_name, c->name)) {
+            continue;
+        }
         if (!should_update_child(c, to)) {
             if (auto_skip) {
                 continue;
@@ -4914,9 +4923,19 @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
                        c->name, from->node_name);
             return -EPERM;
         }
+        if (exactly_one && found) {
+            error_setg(errp, "More than one matching parents found");
+            return -EINVAL;
+        }
+        found = true;
         bdrv_replace_child_tran(c, to, tran);
     }
 
+    if (exactly_one && !found) {
+        error_setg(errp, "No one matching parents found");
+        return -EINVAL;
+    }
+
     return 0;
 }
 
@@ -4966,7 +4985,8 @@ static int bdrv_replace_node_common(BlockDriverState *from,
      * permissions based on new graph. If we fail, we'll roll-back the
      * replacement.
      */
-    ret = bdrv_replace_node_noperm(from, to, auto_skip, tran, errp);
+    ret = bdrv_replace_node_noperm(from, to, auto_skip, NULL, false,
+                                   tran, errp);
     if (ret < 0) {
         goto out;
     }
@@ -5035,7 +5055,8 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
         goto out;
     }
 
-    ret = bdrv_replace_node_noperm(bs_top, bs_new, true, tran, errp);
+    ret = bdrv_replace_node_noperm(bs_top, bs_new, true, NULL, false,
+                                   tran, errp);
     if (ret < 0) {
         goto out;
     }
-- 
2.29.2





More information about the libvir-list mailing list