qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v13 2/3] quorum: implement bdrv_add_child() and


From: Changlong Xie
Subject: Re: [Qemu-devel] [PATCH v13 2/3] quorum: implement bdrv_add_child() and bdrv_del_child()
Date: Wed, 20 Apr 2016 11:36:19 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0

ping...

On 04/13/2016 04:33 PM, Changlong Xie wrote:
From: Wen Congyang <address@hidden>

Signed-off-by: Wen Congyang <address@hidden>
Signed-off-by: zhanghailiang <address@hidden>
Signed-off-by: Gonglei <address@hidden>
Signed-off-by: Changlong Xie <address@hidden>
---
  block.c               |  8 +++---
  block/quorum.c        | 78 +++++++++++++++++++++++++++++++++++++++++++++++++--
  include/block/block.h |  4 +++
  3 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/block.c b/block.c
index 68cd3b2..4bdc6b3 100644
--- a/block.c
+++ b/block.c
@@ -1176,10 +1176,10 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState 
*child_bs,
      return child;
  }

-static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
-                                    BlockDriverState *child_bs,
-                                    const char *child_name,
-                                    const BdrvChildRole *child_role)
+BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
+                             BlockDriverState *child_bs,
+                             const char *child_name,
+                             const BdrvChildRole *child_role)
  {
      BdrvChild *child = bdrv_root_attach_child(child_bs, child_name, 
child_role);
      QLIST_INSERT_HEAD(&parent_bs->children, child, next);
diff --git a/block/quorum.c b/block/quorum.c
index da15465..2553f82 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -14,6 +14,7 @@
   */

  #include "qemu/osdep.h"
+#include "qemu/cutils.h"
  #include "block/block_int.h"
  #include "qapi/qmp/qbool.h"
  #include "qapi/qmp/qdict.h"
@@ -67,6 +68,9 @@ typedef struct QuorumVotes {
  typedef struct BDRVQuorumState {
      BdrvChild **children;  /* children BlockDriverStates */
      int num_children;      /* children count */
+    uint64_t last_index;   /* indicate the child role name of the last
+                            * element of children array
+                            */
      int threshold;         /* if less than threshold children reads gave the
                              * same result a quorum error occurs.
                              */
@@ -898,9 +902,9 @@ static int quorum_open(BlockDriverState *bs, QDict 
*options, int flags,
          ret = -EINVAL;
          goto exit;
      }
-    if (s->num_children < 2) {
+    if (s->num_children < 1) {
          error_setg(&local_err,
-                   "Number of provided children must be greater than 1");
+                   "Number of provided children must be 1 or more");
          ret = -EINVAL;
          goto exit;
      }
@@ -964,6 +968,7 @@ static int quorum_open(BlockDriverState *bs, QDict 
*options, int flags,

          opened[i] = true;
      }
+    s->last_index = s->num_children;

      g_free(opened);
      goto exit;
@@ -1020,6 +1025,72 @@ static void quorum_attach_aio_context(BlockDriverState 
*bs,
      }
  }

+static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
+                             Error **errp)
+{
+    BDRVQuorumState *s = bs->opaque;
+    BdrvChild *child;
+    char indexstr[32];
+    int ret;
+
+    assert(s->num_children <= INT_MAX / sizeof(BdrvChild *) &&
+           s->last_index <= UINT64_MAX);
+    if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
+        s->last_index == UINT64_MAX) {
+        error_setg(errp, "Too many children");
+        return;
+    }
+
+    ret = snprintf(indexstr, 32, "children.%" PRIu64, s->last_index);
+    if (ret < 0 || ret >= 32) {
+        error_setg(errp, "cannot generate child name");
+        return;
+    }
+    s->last_index++;
+
+    bdrv_drain(bs);
+
+    /* We can safely add the child now */
+    bdrv_ref(child_bs);
+    child = bdrv_attach_child(bs, child_bs, indexstr, &child_format);
+    s->children = g_renew(BdrvChild *, s->children, s->num_children + 1);
+    s->children[s->num_children++] = child;
+}
+
+static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
+                             Error **errp)
+{
+    BDRVQuorumState *s = bs->opaque;
+    int i;
+
+    for (i = 0; i < s->num_children; i++) {
+        if (s->children[i] == child) {
+            break;
+        }
+    }
+
+    /* we have checked it in bdrv_del_child() */
+    assert(i < s->num_children);
+
+    if (s->num_children <= s->threshold) {
+        error_setg(errp,
+            "The number of children cannot be lower than the vote threshold 
%d",
+            s->threshold);
+        return;
+    }
+
+    /* child->name is "children.%d" */
+    assert(!strncmp(child->name, "children.", 9));
+
+    bdrv_drain(bs);
+
+    /* We can safely remove this child now */
+    memmove(&s->children[i], &s->children[i + 1],
+            (s->num_children - i - 1) * sizeof(BdrvChild *));
+    s->children = g_renew(BdrvChild *, s->children, --s->num_children);
+    bdrv_unref_child(bs, child);
+}
+
  static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
  {
      BDRVQuorumState *s = bs->opaque;
@@ -1075,6 +1146,9 @@ static BlockDriver bdrv_quorum = {
      .bdrv_detach_aio_context            = quorum_detach_aio_context,
      .bdrv_attach_aio_context            = quorum_attach_aio_context,

+    .bdrv_add_child                     = quorum_add_child,
+    .bdrv_del_child                     = quorum_del_child,
+
      .is_filter                          = true,
      .bdrv_recurse_is_first_non_filter   = quorum_recurse_is_first_non_filter,
  };
diff --git a/include/block/block.h b/include/block/block.h
index 694ca76..52902cd 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -476,6 +476,10 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs);
  void bdrv_ref(BlockDriverState *bs);
  void bdrv_unref(BlockDriverState *bs);
  void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
+BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
+                             BlockDriverState *child_bs,
+                             const char *child_name,
+                             const BdrvChildRole *child_role);

  bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
  void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);






reply via email to

[Prev in Thread] Current Thread [Next in Thread]