diff mbox

[13/21] blockdev: Add list of monitor-owned BlockBackends

Message ID 1422300468-16216-14-git-send-email-mreitz@redhat.com
State New
Headers show

Commit Message

Max Reitz Jan. 26, 2015, 7:27 p.m. UTC
The monitor does hold references to some BlockBackends so it should have
a list of those BBs; blk_backends is a different list, as it contains
references to all BBs (after a follow-up patch, that is), and that
should not be changed because we do need such a list.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c          | 27 ++++++++++++++++++++++++++-
 blockdev.c                     | 14 ++++++++++++++
 include/sysemu/block-backend.h |  2 ++
 3 files changed, 42 insertions(+), 1 deletion(-)

Comments

Eric Blake Jan. 30, 2015, 5:43 p.m. UTC | #1
On 01/26/2015 12:27 PM, Max Reitz wrote:
> The monitor does hold references to some BlockBackends so it should have
> a list of those BBs; blk_backends is a different list, as it contains
> references to all BBs (after a follow-up patch, that is), and that
> should not be changed because we do need such a list.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c          | 27 ++++++++++++++++++++++++++-
>  blockdev.c                     | 14 ++++++++++++++
>  include/sysemu/block-backend.h |  2 ++
>  3 files changed, 42 insertions(+), 1 deletion(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>
diff mbox

Patch

diff --git a/block/block-backend.c b/block/block-backend.c
index f136fc8..c5ca0f4 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -28,6 +28,7 @@  struct BlockBackend {
     BlockDriverState *bs;
     DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
     QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
+    QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
 
     void *dev;                  /* attached device model, if any */
     /* TODO change to DeviceState when all users are qdevified */
@@ -67,6 +68,11 @@  static void drive_info_del(DriveInfo *dinfo);
 static QTAILQ_HEAD(, BlockBackend) blk_backends =
     QTAILQ_HEAD_INITIALIZER(blk_backends);
 
+/* All BlockBackends referenced by the monitor and which are iterated through by
+ * blk_next() */
+static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
+    QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
+
 /*
  * Create a new BlockBackend with @name, with a reference count of one.
  * @name must not be null or empty.
@@ -228,7 +234,8 @@  void blk_unref(BlockBackend *blk, Notifier *close_all_notifier)
  */
 BlockBackend *blk_next(BlockBackend *blk)
 {
-    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
+    return blk ? QTAILQ_NEXT(blk, monitor_link)
+               : QTAILQ_FIRST(&monitor_block_backends);
 }
 
 /*
@@ -247,6 +254,24 @@  BlockBackend *blk_next_inserted(BlockBackend *blk)
 }
 
 /*
+ * Add a BlockBackend into the list of backends referenced by the monitor.
+ * Strictly for use by blockdev.c.
+ */
+void monitor_add_blk(BlockBackend *blk)
+{
+    QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
+}
+
+/*
+ * Remove a BlockBackend from the list of backends referenced by the monitor.
+ * Strictly for use by blockdev.c.
+ */
+void monitor_remove_blk(BlockBackend *blk)
+{
+    QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
+}
+
+/*
  * Return @blk's name, a non-null string.
  * Wart: the name is empty iff @blk has been hidden with
  * blk_hide_on_behalf_of_do_drive_del().
diff --git a/blockdev.c b/blockdev.c
index 22d7ceb..0f965bd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -90,6 +90,8 @@  static int if_max_devs[IF_COUNT] = {
 static void monitor_blk_unref_with_can(BlockBackend *blk,
                                        BlockdevCloseAllNotifier *can)
 {
+    BlockBackend *blk1 = NULL;
+
     if (can) {
         assert(can->blk == blk);
     } else {
@@ -101,6 +103,15 @@  static void monitor_blk_unref_with_can(BlockBackend *blk,
         assert(can);
     }
 
+    /* Thanks to do_drive_del() magic, the BlockBackend is not necessarily
+     * listed at this point */
+    while ((blk1 = blk_next(blk1)) != NULL) {
+        if (blk1 == blk) {
+            monitor_remove_blk(blk);
+            break;
+        }
+    }
+
     blk_unref(blk, &can->n);
     QTAILQ_REMOVE(&close_all_notifiers, can, next);
     g_free(can);
@@ -634,6 +645,8 @@  static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
 
     blk_set_on_error(blk, on_read_error, on_write_error);
 
+    monitor_add_blk(blk);
+
 err_no_bs_opts:
     qemu_opts_del(opts);
     return blk;
@@ -2294,6 +2307,7 @@  int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
      */
     if (blk_get_attached_dev(blk)) {
         blk_hide_on_behalf_of_do_drive_del(blk);
+        monitor_remove_blk(blk);
         /* Further I/O must not pause the guest */
         blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
                          BLOCKDEV_ON_ERROR_REPORT);
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 73b26ad..1683732 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -75,6 +75,8 @@  BlockBackend *blk_by_name(const char *name);
 bool blk_name_taken(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 BlockBackend *blk_next_inserted(BlockBackend *blk);
+void monitor_add_blk(BlockBackend *blk);
+void monitor_remove_blk(BlockBackend *blk);
 
 BlockDriverState *blk_bs(BlockBackend *blk);
 void blk_remove_bs(BlockBackend *blk);