qemu-block
[Top][All Lists]
Advanced

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

Re: [Qemu-block] [PATCH v3 02/12] block: Add op blocker notifier list


From: Max Reitz
Subject: Re: [Qemu-block] [PATCH v3 02/12] block: Add op blocker notifier list
Date: Mon, 18 May 2015 19:22:48 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0

On 15.05.2015 08:04, Fam Zheng wrote:
BDS users can register a notifier and get notified about op blocker
changes.

Signed-off-by: Fam Zheng <address@hidden>
---
  block.c                   | 35 +++++++++++++++++++++++++++++++++++
  include/block/block.h     |  8 ++++++++
  include/block/block_int.h |  3 +++
  3 files changed, 46 insertions(+)

diff --git a/block.c b/block.c
index 7904098..178e186 100644
--- a/block.c
+++ b/block.c
@@ -3375,6 +3375,19 @@ struct BdrvOpBlocker {
      QLIST_ENTRY(BdrvOpBlocker) list;
  };
+/* Add a notifier which will be notified when the first blocker of some type is
+ * added to bs, or when the last blocker is removed. The notifier handler
+ * should receive a BlockOpEvent data.
+ *
+ * Caller must hold bs->aio_context; the notifier handler is also called with
+ * it hold.

*held (I think)

With that fixed:

Reviewed-by: Max Reitz <address@hidden>

(Although I'm missing a place where the notifiers are freed (on bdrv_delete()/bdrv_close()), but maybe that's done in a different patch)

+ */
+void bdrv_op_blocker_add_notifier(BlockDriverState *bs,
+                                  Notifier *notifier)
+{
+    notifier_list_add(&bs->op_blocker_notifiers, notifier);
+}
+
  bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
  {
      BdrvOpBlocker *blocker;
@@ -3391,26 +3404,48 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, 
BlockOpType op, Error **errp)
      return false;
  }
+static void bdrv_op_blocker_notify(BlockDriverState *bs, BlockOpType op,
+                                   Error *reason, bool blocking)
+{
+    BlockOpEvent event = (BlockOpEvent) {
+        op = op,
+        reason = reason,
+        blocking = blocking,
+    };
+
+    notifier_list_notify(&bs->op_blocker_notifiers, &event);
+}
+
  void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason)
  {
+    bool blocked;
      BdrvOpBlocker *blocker;
      assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
blocker = g_new0(BdrvOpBlocker, 1);
      blocker->reason = reason;
+    blocked = !QLIST_EMPTY(&bs->op_blockers[op]);
      QLIST_INSERT_HEAD(&bs->op_blockers[op], blocker, list);
+    if (!blocked) {
+        bdrv_op_blocker_notify(bs, op, reason, true);
+    }
  }
void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason)
  {
+    bool blocked;
      BdrvOpBlocker *blocker, *next;
      assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
+    blocked = !QLIST_EMPTY(&bs->op_blockers[op]);
      QLIST_FOREACH_SAFE(blocker, &bs->op_blockers[op], list, next) {
          if (blocker->reason == reason) {
              QLIST_REMOVE(blocker, list);
              g_free(blocker);
          }
      }
+    if (blocked && QLIST_EMPTY(&bs->op_blockers[op])) {
+        bdrv_op_blocker_notify(bs, op, reason, false);
+    }
  }
void bdrv_op_block_all(BlockDriverState *bs, Error *reason)
diff --git a/include/block/block.h b/include/block/block.h
index 906fb31..3420b2c 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -163,6 +163,12 @@ typedef enum BlockOpType {
      BLOCK_OP_TYPE_MAX,
  } BlockOpType;
+typedef struct {
+    BlockOpType type;
+    Error *reason;
+    bool blocking;
+} BlockOpEvent;
+
  void bdrv_iostatus_enable(BlockDriverState *bs);
  void bdrv_iostatus_reset(BlockDriverState *bs);
  void bdrv_iostatus_disable(BlockDriverState *bs);
@@ -491,6 +497,8 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs);
  void bdrv_ref(BlockDriverState *bs);
  void bdrv_unref(BlockDriverState *bs);
+void bdrv_op_blocker_add_notifier(BlockDriverState *bs,
+                                  Notifier *notifier);
  bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
  void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);
  void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index db29b74..29d1c84 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -418,6 +418,9 @@ struct BlockDriverState {
      /* operation blockers */
      QLIST_HEAD(, BdrvOpBlocker) op_blockers[BLOCK_OP_TYPE_MAX];
+ /* Callback when one list in op_blockers has "empty" status change. */
+    NotifierList op_blocker_notifiers;
+
      /* long-running background operation */
      BlockJob *job;




reply via email to

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