diff mbox

[v5,10/13] blockdev: Keep track of monitor-owned BDS

Message ID 1425413591-31413-11-git-send-email-mreitz@redhat.com
State New
Headers show

Commit Message

Max Reitz March 3, 2015, 8:13 p.m. UTC
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                                |  2 ++
 blockdev.c                             | 18 ++++++++++++++++++
 include/block/block_int.h              |  4 ++++
 stubs/Makefile.objs                    |  1 +
 stubs/blockdev-close-all-bdrv-states.c |  5 +++++
 5 files changed, 30 insertions(+)
 create mode 100644 stubs/blockdev-close-all-bdrv-states.c

Comments

Eric Blake March 19, 2015, 7:18 p.m. UTC | #1
On 03/03/2015 01:13 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block.c                                |  2 ++
>  blockdev.c                             | 18 ++++++++++++++++++
>  include/block/block_int.h              |  4 ++++
>  stubs/Makefile.objs                    |  1 +
>  stubs/blockdev-close-all-bdrv-states.c |  5 +++++
>  5 files changed, 30 insertions(+)
>  create mode 100644 stubs/blockdev-close-all-bdrv-states.c

Again, might be nice for the commit message to document why adding this
is useful, but doesn't affect the code.

Reviewed-by: Eric Blake <eblake@redhat.com>
Markus Armbruster March 20, 2015, 8:04 a.m. UTC | #2
Eric Blake <eblake@redhat.com> writes:

> On 03/03/2015 01:13 PM, Max Reitz wrote:
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>  block.c                                |  2 ++
>>  blockdev.c                             | 18 ++++++++++++++++++
>>  include/block/block_int.h              |  4 ++++
>>  stubs/Makefile.objs                    |  1 +
>>  stubs/blockdev-close-all-bdrv-states.c |  5 +++++
>>  5 files changed, 30 insertions(+)
>>  create mode 100644 stubs/blockdev-close-all-bdrv-states.c
>
> Again, might be nice for the commit message to document why adding this
> is useful, but doesn't affect the code.
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Might be nice?  This absolutely needs an explanation, in the code!

Why do we need a separate list of "monitor-owned BDS"?

What makes a BDS "monitor-owned"?

What are the invariants governing relations among bdrv_states,
graph_bdrv_states (what a horrible name) and blk_backends?
Max Reitz March 20, 2015, 12:52 p.m. UTC | #3
On 2015-03-20 at 04:04, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
>
>> On 03/03/2015 01:13 PM, Max Reitz wrote:
>>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>>> ---
>>>   block.c                                |  2 ++
>>>   blockdev.c                             | 18 ++++++++++++++++++
>>>   include/block/block_int.h              |  4 ++++
>>>   stubs/Makefile.objs                    |  1 +
>>>   stubs/blockdev-close-all-bdrv-states.c |  5 +++++
>>>   5 files changed, 30 insertions(+)
>>>   create mode 100644 stubs/blockdev-close-all-bdrv-states.c
>> Again, might be nice for the commit message to document why adding this
>> is useful, but doesn't affect the code.
>>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
> Might be nice?  This absolutely needs an explanation, in the code!
>
> Why do we need a separate list of "monitor-owned BDS"?

I thought it self-evident, but you're right, of course: The concept 
being that the monitor can hold references to BDS ("owning them", see 
below), of course it should keep track of those references (which I 
thought didn't need an explanation, because if you hold a reference, 
well, you better actually hold one).

> What makes a BDS "monitor-owned"?

Being created explicitly.

BDS created implicitly because a BB was created (-drive, blockdev-add 
with @id; in these cases, the BBs are monitor-owned) or that are not the 
root of a BDS tree (thus created implicitly in that tree) are not 
monitor-owned. All BDS created explicitly (blockdev-add without @id) are 
monitor-owned.

> What are the invariants governing relations among bdrv_states,
> graph_bdrv_states (what a horrible name) and blk_backends?

bdrv_states is removed in the follow-up series. I think it's legacy 
cruft which we needed at a time where we did not have BlockBackends: It 
tracks all the BDSs with a BB, basically (a BDS is inserted there in 
bdrv_new_root() which is only called from blk_new_with_bs()). Therefore, 
we don't need it, as we have a list of all the BBs already.

graph_bdrv_states tracks all BDSs with a node name. We need that because 
we want to find BDSs by node name.

blk_backends, which supersedes bdrv_states, basically, will, after the 
follow-up, contain every single BlockBackend there is. It will be 
different from monitor_block_backends (follow-up...) in that the latter 
only contains the monitor-owned BBs.

Why we need that difference is a question for the follow-up. However, I 
can answer it here, too: We do have some operations that should actually 
be run over all BlockBackends, like blk_name_taken(), blk_drain_all(), 
blk_flush_all(), and so on. However, all the BBs that are not 
monitor-owned should not be visible to the user (the monitor!), so for 
operations like blk_by_name() or qmp_query_blockstats(), only the 
monitor-owned BBs should be considered.

What makes a BB monitor-owned? It's monitor-owned if it has been created 
using -drive or blockdev-add. Are there any other BBs right now? Except 
for qemu-{img,io,nbd}, there is only xen_disk.c, so practically, no.

What makes a BB monitor-unowned? Deleting its reference through a 
monitor command while there are still other users (in theory that would 
be NBD, block jobs, etc., although I don't know whether that actually 
works that way right now). So it is probably possible to have 
non-monitor-owned BBs, but those should not be visible to the user. 
However, we need to consider them inside of the block layer whenever we 
want to do something for actually all the BBs.

Side note: As far as I know, we currently only have drive_del to drop 
the monitor reference to a BB. What happens there before the follow-up 
is the BB is made anonymous and removed from blk_backends 
(blk_hide_on_behalf_of_hmp_drive_del()) and the root BDS from 
bdrv_states (it's really redundant), so before that series, blk_backends 
is basically the list of monitor-owned BBs (which I don't think is 
right, it should contain all BBs, and we need a separate list for the 
monitor-owned ones).

I hope I was able to explain myself.

Max
diff mbox

Patch

diff --git a/block.c b/block.c
index 9698b1d..fce9d5d 100644
--- a/block.c
+++ b/block.c
@@ -2097,6 +2097,8 @@  static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     bs_dest->device_list = bs_src->device_list;
     /* keep the same entry in all_bdrv_states */
     bs_dest->bs_list = bs_src->bs_list;
+    /* keep the same entry in the list of monitor-owned BDS */
+    bs_dest->monitor_list = bs_src->monitor_list;
 
     bs_dest->blk = bs_src->blk;
 
diff --git a/blockdev.c b/blockdev.c
index 546acfe..a4283a7 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -47,6 +47,9 @@ 
 #include "trace.h"
 #include "sysemu/arch_init.h"
 
+static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
+    QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
+
 static const char *const if_name[IF_COUNT] = {
     [IF_NONE] = "none",
     [IF_IDE] = "ide",
@@ -646,6 +649,19 @@  fail:
     return NULL;
 }
 
+void blockdev_close_all_bdrv_states(void)
+{
+    BlockDriverState *bs, *next_bs;
+
+    QTAILQ_FOREACH_SAFE(bs, &monitor_bdrv_states, monitor_list, next_bs) {
+        AioContext *ctx = bdrv_get_aio_context(bs);
+
+        aio_context_acquire(ctx);
+        bdrv_unref(bs);
+        aio_context_release(ctx);
+    }
+}
+
 static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to,
                             Error **errp)
 {
@@ -3161,6 +3177,8 @@  void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
         if (!bs) {
             goto fail;
         }
+
+        QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list);
     }
 
     if (bs && bdrv_key_required(bs)) {
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 622fbfc..f9968da 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -401,6 +401,8 @@  struct BlockDriverState {
     QTAILQ_ENTRY(BlockDriverState) device_list;
     /* element of the list of all BlockDriverStates (all_bdrv_states) */
     QTAILQ_ENTRY(BlockDriverState) bs_list;
+    /* element of the list of monitor-owned BDS */
+    QTAILQ_ENTRY(BlockDriverState) monitor_list;
     QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
     int refcnt;
 
@@ -624,4 +626,6 @@  bool blk_dev_is_tray_open(BlockBackend *blk);
 bool blk_dev_is_medium_locked(BlockBackend *blk);
 void blk_dev_resize_cb(BlockBackend *blk);
 
+void blockdev_close_all_bdrv_states(void);
+
 #endif /* BLOCK_INT_H */
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 5e347d0..9169a09 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,5 +1,6 @@ 
 stub-obj-y += arch-query-cpu-def.o
 stub-obj-y += bdrv-commit-all.o
+stub-obj-y += blockdev-close-all-bdrv-states.o
 stub-obj-y += chr-baum-init.o
 stub-obj-y += chr-msmouse.o
 stub-obj-y += chr-testdev.o
diff --git a/stubs/blockdev-close-all-bdrv-states.c b/stubs/blockdev-close-all-bdrv-states.c
new file mode 100644
index 0000000..12d2442
--- /dev/null
+++ b/stubs/blockdev-close-all-bdrv-states.c
@@ -0,0 +1,5 @@ 
+#include "block/block_int.h"
+
+void blockdev_close_all_bdrv_states(void)
+{
+}