Blame SOURCES/kvm-block-Add-auto-read-only-option.patch

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