yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
26ba25
From cff7af832cadce3d5afd2819483b1b61a115ace2 Mon Sep 17 00:00:00 2001
26ba25
From: Kevin Wolf <kwolf@redhat.com>
26ba25
Date: Thu, 10 Jan 2019 12:44:32 +0000
26ba25
Subject: [PATCH 02/14] block: Add auto-read-only option
26ba25
26ba25
RH-Author: Kevin Wolf <kwolf@redhat.com>
26ba25
Message-id: <20190110124442.30132-3-kwolf@redhat.com>
26ba25
Patchwork-id: 83952
26ba25
O-Subject: [RHEL-8.0 qemu-kvm PATCH 02/12] block: Add auto-read-only option
26ba25
Bugzilla: 1644996
26ba25
RH-Acked-by: Max Reitz <mreitz@redhat.com>
26ba25
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
26ba25
RH-Acked-by: Eric Blake <eblake@redhat.com>
26ba25
26ba25
If a management application builds the block graph node by node, the
26ba25
protocol layer doesn't inherit its read-only option from the format
26ba25
layer any more, so it must be set explicitly.
26ba25
26ba25
Backing files should work on read-only storage, but at the same time, a
26ba25
block job like commit should be able to reopen them read-write if they
26ba25
are on read-write storage. However, without option inheritance, reopen
26ba25
only changes the read-only option for the root node (typically the
26ba25
format layer), but not the protocol layer, so reopening fails (the
26ba25
format layer wants to get write permissions, but the protocol layer is
26ba25
still read-only).
26ba25
26ba25
A simple workaround for the problem in the management tool would be to
26ba25
open the protocol layer always read-write and to make only the format
26ba25
layer read-only for backing files. However, sometimes the file is
26ba25
actually stored on read-only storage and we don't know whether the image
26ba25
can be opened read-write (for example, for NBD it depends on the server
26ba25
we're trying to connect to). This adds an option that makes QEMU try to
26ba25
open the image read-write, but allows it to degrade to a read-only mode
26ba25
without returning an error.
26ba25
26ba25
The documentation for this option is consciously phrased in a way that
26ba25
allows QEMU to switch to a better model eventually: Instead of trying
26ba25
when the image is first opened, making the read-only flag dynamic and
26ba25
changing it automatically whenever the first BLK_PERM_WRITE user is
26ba25
attached or the last one is detached would be much more useful
26ba25
behaviour.
26ba25
26ba25
Unfortunately, this more useful behaviour is also a lot harder to
26ba25
implement, and libvirt needs a solution now before it can switch to
26ba25
-blockdev, so let's start with this easier approach for now.
26ba25
26ba25
Instead of adding a new auto-read-only option, turning the existing
26ba25
read-only into an enum (with a bool alternate for compatibility) was
26ba25
considered, but it complicated the implementation to the point that it
26ba25
didn't seem to be worth it.
26ba25
26ba25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26ba25
Reviewed-by: Eric Blake <eblake@redhat.com>
26ba25
(cherry picked from commit e35bdc123a4ace9f4d3fccaaf88907014e2438cd)
26ba25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26ba25
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
26ba25
---
26ba25
 block.c               | 17 +++++++++++++++++
26ba25
 block/vvfat.c         |  1 +
26ba25
 blockdev.c            |  2 +-
26ba25
 include/block/block.h |  2 ++
26ba25
 qapi/block-core.json  |  7 +++++++
26ba25
 5 files changed, 28 insertions(+), 1 deletion(-)
26ba25
26ba25
diff --git a/block.c b/block.c
26ba25
index 6f1d53b..f357975 100644
26ba25
--- a/block.c
26ba25
+++ b/block.c
26ba25
@@ -905,6 +905,7 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
26ba25
 
26ba25
     /* Inherit the read-only option from the parent if it's not set */
26ba25
     qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
26ba25
+    qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
26ba25
 
26ba25
     /* Our block drivers take care to send flushes and respect unmap policy,
26ba25
      * so we can default to enable both on lower layers regardless of the
26ba25
@@ -1028,6 +1029,7 @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
26ba25
 
26ba25
     /* backing files always opened read-only */
26ba25
     qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
26ba25
+    qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
26ba25
     flags &= ~BDRV_O_COPY_ON_READ;
26ba25
 
26ba25
     /* snapshot=on is handled on the top layer */
26ba25
@@ -1117,6 +1119,10 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
26ba25
         *flags |= BDRV_O_RDWR;
26ba25
     }
26ba25
 
26ba25
+    assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
26ba25
+    if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
26ba25
+        *flags |= BDRV_O_AUTO_RDONLY;
26ba25
+    }
26ba25
 }
26ba25
 
26ba25
 static void update_options_from_flags(QDict *options, int flags)
26ba25
@@ -1131,6 +1137,10 @@ static void update_options_from_flags(QDict *options, int flags)
26ba25
     if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
26ba25
         qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
26ba25
     }
26ba25
+    if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
26ba25
+        qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
26ba25
+                       flags & BDRV_O_AUTO_RDONLY);
26ba25
+    }
26ba25
 }
26ba25
 
26ba25
 static void bdrv_assign_node_name(BlockDriverState *bs,
26ba25
@@ -1304,6 +1314,11 @@ QemuOptsList bdrv_runtime_opts = {
26ba25
             .help = "Node is opened in read-only mode",
26ba25
         },
26ba25
         {
26ba25
+            .name = BDRV_OPT_AUTO_READ_ONLY,
26ba25
+            .type = QEMU_OPT_BOOL,
26ba25
+            .help = "Node can become read-only if opening read-write fails",
26ba25
+        },
26ba25
+        {
26ba25
             .name = "detect-zeroes",
26ba25
             .type = QEMU_OPT_STRING,
26ba25
             .help = "try to optimize zero writes (off, on, unmap)",
26ba25
@@ -2490,6 +2505,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
26ba25
         qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
26ba25
         qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
26ba25
         qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
26ba25
+        qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
26ba25
+
26ba25
     }
26ba25
 
26ba25
     bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
26ba25
diff --git a/block/vvfat.c b/block/vvfat.c
26ba25
index c7d2ed2..3efce9e 100644
26ba25
--- a/block/vvfat.c
26ba25
+++ b/block/vvfat.c
26ba25
@@ -3130,6 +3130,7 @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
26ba25
                                int parent_flags, QDict *parent_options)
26ba25
 {
26ba25
     qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
26ba25
+    qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
26ba25
     qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
26ba25
 }
26ba25
 
26ba25
diff --git a/blockdev.c b/blockdev.c
26ba25
index 56a3d0f..be650d0 100644
26ba25
--- a/blockdev.c
26ba25
+++ b/blockdev.c
26ba25
@@ -2760,7 +2760,7 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
26ba25
 
26ba25
     bdrv_flags = blk_get_open_flags_from_root_state(blk);
26ba25
     bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
26ba25
-        BDRV_O_PROTOCOL);
26ba25
+        BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
26ba25
 
26ba25
     if (!has_read_only) {
26ba25
         read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
26ba25
diff --git a/include/block/block.h b/include/block/block.h
26ba25
index 8e78daf..6ee8b2a 100644
26ba25
--- a/include/block/block.h
26ba25
+++ b/include/block/block.h
26ba25
@@ -114,6 +114,7 @@ typedef struct HDGeometry {
26ba25
                                       select an appropriate protocol driver,
26ba25
                                       ignoring the format layer */
26ba25
 #define BDRV_O_NO_IO       0x10000 /* don't initialize for I/O */
26ba25
+#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
26ba25
 
26ba25
 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
26ba25
 
26ba25
@@ -124,6 +125,7 @@ typedef struct HDGeometry {
26ba25
 #define BDRV_OPT_CACHE_DIRECT   "cache.direct"
26ba25
 #define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
26ba25
 #define BDRV_OPT_READ_ONLY      "read-only"
26ba25
+#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
26ba25
 #define BDRV_OPT_DISCARD        "discard"
26ba25
 #define BDRV_OPT_FORCE_SHARE    "force-share"
26ba25
 
26ba25
diff --git a/qapi/block-core.json b/qapi/block-core.json
26ba25
index db47fb8..5e5f4f9 100644
26ba25
--- a/qapi/block-core.json
26ba25
+++ b/qapi/block-core.json
26ba25
@@ -3604,6 +3604,12 @@
26ba25
 #                 either generally or in certain configurations. In this case,
26ba25
 #                 the default value does not work and the option must be
26ba25
 #                 specified explicitly.
26ba25
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
26ba25
+#                  decide not to open the image read-write as requested, but
26ba25
+#                  fall back to read-only instead (and switch between the modes
26ba25
+#                  later), e.g. depending on whether the image file is writable
26ba25
+#                  or whether a writing user is attached to the node
26ba25
+#                  (default: false, since 3.1)
26ba25
 # @detect-zeroes: detect and optimize zero writes (Since 2.1)
26ba25
 #                 (default: off)
26ba25
 # @force-share:   force share all permission on added nodes.
26ba25
@@ -3619,6 +3625,7 @@
26ba25
             '*discard': 'BlockdevDiscardOptions',
26ba25
             '*cache': 'BlockdevCacheOptions',
26ba25
             '*read-only': 'bool',
26ba25
+            '*auto-read-only': 'bool',
26ba25
             '*force-share': 'bool',
26ba25
             '*detect-zeroes': 'BlockdevDetectZeroesOptions' },
26ba25
   'discriminator': 'driver',
26ba25
-- 
26ba25
1.8.3.1
26ba25