diff mbox series

[RFC,05/10] block: Add 'keep_old_opts' parameter to bdrv_reopen_queue()

Message ID 4a1c8fb9816de2115d08284c36d7a718b5e48de6.1528991017.git.berto@igalia.com
State New
Headers show
Series Add a 'x-blockdev-reopen' QMP command | expand

Commit Message

Alberto Garcia June 14, 2018, 3:49 p.m. UTC
The bdrv_reopen_queue() function is used to create a queue with the
BDSs that are going to be reopened and their new options. Once the
queue is ready bdrv_reopen_multiple() is called to perform the
operation.

The original options from each one of the BDSs are kept, with the new
options passed to bdrv_reopen_queue() applied on top of them.

For "x-blockdev-reopen" we want a function that behaves much like
"blockdev-add". We want to ignore the previous set of options so that
only the ones actually specified by the user are applied, with the
rest having their default values.

We can achieve this by adding a new parameter to bdrv_reopen_queue()
that specifies whether the old set of options is kept or discarded
when building the reopen queue. All current callers will set that
parameter to true, but x-blockdev-reopen will set it to false.

Signed-off-by: Alberto Garcia <berto@igalia.com>
---
 block.c               | 34 +++++++++++++++++++---------------
 block/replication.c   |  4 ++--
 include/block/block.h |  3 ++-
 qemu-io-cmds.c        |  2 +-
 4 files changed, 24 insertions(+), 19 deletions(-)

Comments

Kevin Wolf June 18, 2018, 2:15 p.m. UTC | #1
Am 14.06.2018 um 17:49 hat Alberto Garcia geschrieben:
> The bdrv_reopen_queue() function is used to create a queue with the
> BDSs that are going to be reopened and their new options. Once the
> queue is ready bdrv_reopen_multiple() is called to perform the
> operation.
> 
> The original options from each one of the BDSs are kept, with the new
> options passed to bdrv_reopen_queue() applied on top of them.
> 
> For "x-blockdev-reopen" we want a function that behaves much like
> "blockdev-add". We want to ignore the previous set of options so that
> only the ones actually specified by the user are applied, with the
> rest having their default values.
> 
> We can achieve this by adding a new parameter to bdrv_reopen_queue()
> that specifies whether the old set of options is kept or discarded
> when building the reopen queue. All current callers will set that
> parameter to true, but x-blockdev-reopen will set it to false.
> 
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> ---
>  block.c               | 34 +++++++++++++++++++---------------
>  block/replication.c   |  4 ++--
>  include/block/block.h |  3 ++-
>  qemu-io-cmds.c        |  2 +-
>  4 files changed, 24 insertions(+), 19 deletions(-)
> 
> diff --git a/block.c b/block.c
> index a741300fae..0b9268a48d 100644
> --- a/block.c
> +++ b/block.c
> @@ -2850,7 +2850,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
>                                                   int flags,
>                                                   const BdrvChildRole *role,
>                                                   QDict *parent_options,
> -                                                 int parent_flags)
> +                                                 int parent_flags,
> +                                                 bool keep_old_opts)

Can we change the semantics of keep_old_opts so that flags is completely
ignored for keep_old_opts=false?

Flags are one of the reasons why the behaviour of bdrv_reopen() is
rather complex and I'd prefer not having that complexity in a public
interface. To be honest, I wouldn't be sure that I could write a correct
documentation with it.

Kevin
Alberto Garcia June 18, 2018, 3:28 p.m. UTC | #2
On Mon 18 Jun 2018 04:15:07 PM CEST, Kevin Wolf wrote:

>> @@ -2850,7 +2850,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
>>                                                   int flags,
>>                                                   const BdrvChildRole *role,
>>                                                   QDict *parent_options,
>> -                                                 int parent_flags)
>> +                                                 int parent_flags,
>> +                                                 bool keep_old_opts)
>
> Can we change the semantics of keep_old_opts so that flags is completely
> ignored for keep_old_opts=false?
>
> Flags are one of the reasons why the behaviour of bdrv_reopen() is
> rather complex and I'd prefer not having that complexity in a public
> interface. To be honest, I wouldn't be sure that I could write a
> correct documentation with it.

I think so. In this series if keep_old_opts is false the only possible
flags are either 0 or BDRV_O_RDWR | BDRV_O_ALLOW_RDWR, depending on the
value of "read-only" option.

Berto
Kevin Wolf June 18, 2018, 4:15 p.m. UTC | #3
Am 18.06.2018 um 17:28 hat Alberto Garcia geschrieben:
> On Mon 18 Jun 2018 04:15:07 PM CEST, Kevin Wolf wrote:
> 
> >> @@ -2850,7 +2850,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
> >>                                                   int flags,
> >>                                                   const BdrvChildRole *role,
> >>                                                   QDict *parent_options,
> >> -                                                 int parent_flags)
> >> +                                                 int parent_flags,
> >> +                                                 bool keep_old_opts)
> >
> > Can we change the semantics of keep_old_opts so that flags is completely
> > ignored for keep_old_opts=false?
> >
> > Flags are one of the reasons why the behaviour of bdrv_reopen() is
> > rather complex and I'd prefer not having that complexity in a public
> > interface. To be honest, I wouldn't be sure that I could write a
> > correct documentation with it.
> 
> I think so. In this series if keep_old_opts is false the only possible
> flags are either 0 or BDRV_O_RDWR | BDRV_O_ALLOW_RDWR, depending on the
> value of "read-only" option.

I assume the default options that you have to set in
qmp_x_blockdev_reopen() are only because update_options_from_flags()
would break things otherwise. So if we get rid of the latter, maybe we
can simplify qmp_x_blockdev_reopen(), too.

Well, or maybe my assumption is just wrong, of course.

KEvin
diff mbox series

Patch

diff --git a/block.c b/block.c
index a741300fae..0b9268a48d 100644
--- a/block.c
+++ b/block.c
@@ -2850,7 +2850,8 @@  static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
                                                  int flags,
                                                  const BdrvChildRole *role,
                                                  QDict *parent_options,
-                                                 int parent_flags)
+                                                 int parent_flags,
+                                                 bool keep_old_opts)
 {
     assert(bs != NULL);
 
@@ -2899,13 +2900,13 @@  static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
     }
 
     /* Old explicitly set values (don't overwrite by inherited value) */
-    if (bs_entry) {
-        old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
-    } else {
-        old_options = qdict_clone_shallow(bs->explicit_options);
+    if (bs_entry || keep_old_opts) {
+        old_options = qdict_clone_shallow(bs_entry ?
+                                          bs_entry->state.explicit_options :
+                                          bs->explicit_options);
+        bdrv_join_options(bs, options, old_options);
+        qobject_unref(old_options);
     }
-    bdrv_join_options(bs, options, old_options);
-    qobject_unref(old_options);
 
     explicit_options = qdict_clone_shallow(options);
 
@@ -2923,10 +2924,12 @@  static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
         qobject_unref(options_copy);
     }
 
-    /* Old values are used for options that aren't set yet */
-    old_options = qdict_clone_shallow(bs->options);
-    bdrv_join_options(bs, options, old_options);
-    qobject_unref(old_options);
+    if (keep_old_opts) {
+        /* Old values are used for options that aren't set yet */
+        old_options = qdict_clone_shallow(bs->options);
+        bdrv_join_options(bs, options, old_options);
+        qobject_unref(old_options);
+    }
 
     /* bdrv_open_inherit() sets and clears some additional flags internally */
     flags &= ~BDRV_O_PROTOCOL;
@@ -2967,7 +2970,7 @@  static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
         g_free(child_key_dot);
 
         bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, 0,
-                                child->role, options, flags);
+                                child->role, options, flags, keep_old_opts);
     }
 
     return bs_queue;
@@ -2975,10 +2978,11 @@  static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 
 BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
                                     BlockDriverState *bs,
-                                    QDict *options, int flags)
+                                    QDict *options, int flags,
+                                    bool keep_old_opts)
 {
     return bdrv_reopen_queue_child(bs_queue, bs, options, flags,
-                                   NULL, NULL, 0);
+                                   NULL, NULL, 0, keep_old_opts);
 }
 
 /*
@@ -3049,7 +3053,7 @@  int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
 
     bdrv_subtree_drained_begin(bs);
 
-    queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
+    queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags, true);
     ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
diff --git a/block/replication.c b/block/replication.c
index 826db7b304..af984c29dd 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -401,12 +401,12 @@  static void reopen_backing_file(BlockDriverState *bs, bool writable,
 
     if (orig_hidden_flags != new_hidden_flags) {
         reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL,
-                                         new_hidden_flags);
+                                         new_hidden_flags, true);
     }
 
     if (!(orig_secondary_flags & BDRV_O_RDWR)) {
         reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
-                                         NULL, new_secondary_flags);
+                                         NULL, new_secondary_flags, true);
     }
 
     if (reopen_queue) {
diff --git a/include/block/block.h b/include/block/block.h
index 9306c986ef..c8654dde65 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -267,7 +267,8 @@  BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
                                        int flags, Error **errp);
 BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
                                     BlockDriverState *bs,
-                                    QDict *options, int flags);
+                                    QDict *options, int flags,
+                                    bool keep_old_opts);
 int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp);
 int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
 int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 5bf5f28178..4742358b1a 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -2050,7 +2050,7 @@  static int reopen_f(BlockBackend *blk, int argc, char **argv)
     qemu_opts_reset(&reopen_opts);
 
     bdrv_subtree_drained_begin(bs);
-    brq = bdrv_reopen_queue(NULL, bs, opts, flags);
+    brq = bdrv_reopen_queue(NULL, bs, opts, flags, true);
     bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
     bdrv_subtree_drained_end(bs);