Blame SOURCES/kvm-block-Base-permissions-on-rw-state-after-reopen.patch

4a2fec
From 35806318c04a6d8450ed745d1921a07915c3cc16 Mon Sep 17 00:00:00 2001
4a2fec
From: Kevin Wolf <kwolf@redhat.com>
4a2fec
Date: Mon, 4 Dec 2017 12:10:03 +0100
4a2fec
Subject: [PATCH 32/36] block: Base permissions on rw state after reopen
4a2fec
4a2fec
RH-Author: Kevin Wolf <kwolf@redhat.com>
4a2fec
Message-id: <20171204121007.12964-5-kwolf@redhat.com>
4a2fec
Patchwork-id: 78109
4a2fec
O-Subject: [RHV-7.5 qemu-kvm-rhev PATCH v2 4/8] block: Base permissions on rw state after reopen
4a2fec
Bugzilla: 1492178
4a2fec
RH-Acked-by: Fam Zheng <famz@redhat.com>
4a2fec
RH-Acked-by: Max Reitz <mreitz@redhat.com>
4a2fec
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
4a2fec
4a2fec
When new permissions are calculated during bdrv_reopen(), they need to
4a2fec
be based on the state of the graph as it will be after the reopen has
4a2fec
completed, not on the current state of the involved nodes.
4a2fec
4a2fec
This patch makes bdrv_is_writable() optionally accept a BlockReopenQueue
4a2fec
from which the new flags are taken. This is then used for determining
4a2fec
the new bs->file permissions of format drivers as soon as we add the
4a2fec
code to actually pass a non-NULL reopen queue to the .bdrv_child_perm
4a2fec
callbacks.
4a2fec
4a2fec
While moving bdrv_is_writable(), make it static. It isn't used outside
4a2fec
block.c.
4a2fec
4a2fec
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4a2fec
Reviewed-by: Eric Blake <eblake@redhat.com>
4a2fec
(cherry picked from commit 148eb13c84cccd0eedd6e59f90e0151bd7bac9fa)
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 block.c               | 52 ++++++++++++++++++++++++++++++++++++---------------
4a2fec
 include/block/block.h |  1 -
4a2fec
 2 files changed, 37 insertions(+), 16 deletions(-)
4a2fec
4a2fec
diff --git a/block.c b/block.c
4a2fec
index 5ce773a..5cce274 100644
4a2fec
--- a/block.c
4a2fec
+++ b/block.c
4a2fec
@@ -240,12 +240,6 @@ bool bdrv_is_read_only(BlockDriverState *bs)
4a2fec
     return bs->read_only;
4a2fec
 }
4a2fec
 
4a2fec
-/* Returns whether the image file can be written to right now */
4a2fec
-bool bdrv_is_writable(BlockDriverState *bs)
4a2fec
-{
4a2fec
-    return !bdrv_is_read_only(bs) && !(bs->open_flags & BDRV_O_INACTIVE);
4a2fec
-}
4a2fec
-
4a2fec
 int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
4a2fec
                            bool ignore_allow_rdw, Error **errp)
4a2fec
 {
4a2fec
@@ -1535,6 +1529,41 @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
4a2fec
 static void bdrv_child_abort_perm_update(BdrvChild *c);
4a2fec
 static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
4a2fec
 
4a2fec
+typedef struct BlockReopenQueueEntry {
4a2fec
+     bool prepared;
4a2fec
+     BDRVReopenState state;
4a2fec
+     QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry;
4a2fec
+} BlockReopenQueueEntry;
4a2fec
+
4a2fec
+/*
4a2fec
+ * Return the flags that @bs will have after the reopens in @q have
4a2fec
+ * successfully completed. If @q is NULL (or @bs is not contained in @q),
4a2fec
+ * return the current flags.
4a2fec
+ */
4a2fec
+static int bdrv_reopen_get_flags(BlockReopenQueue *q, BlockDriverState *bs)
4a2fec
+{
4a2fec
+    BlockReopenQueueEntry *entry;
4a2fec
+
4a2fec
+    if (q != NULL) {
4a2fec
+        QSIMPLEQ_FOREACH(entry, q, entry) {
4a2fec
+            if (entry->state.bs == bs) {
4a2fec
+                return entry->state.flags;
4a2fec
+            }
4a2fec
+        }
4a2fec
+    }
4a2fec
+
4a2fec
+    return bs->open_flags;
4a2fec
+}
4a2fec
+
4a2fec
+/* Returns whether the image file can be written to after the reopen queue @q
4a2fec
+ * has been successfully applied, or right now if @q is NULL. */
4a2fec
+static bool bdrv_is_writable(BlockDriverState *bs, BlockReopenQueue *q)
4a2fec
+{
4a2fec
+    int flags = bdrv_reopen_get_flags(q, bs);
4a2fec
+
4a2fec
+    return (flags & (BDRV_O_RDWR | BDRV_O_INACTIVE)) == BDRV_O_RDWR;
4a2fec
+}
4a2fec
+
4a2fec
 static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
4a2fec
                             BdrvChild *c, const BdrvChildRole *role,
4a2fec
                             BlockReopenQueue *reopen_queue,
4a2fec
@@ -1572,7 +1601,7 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
4a2fec
 
4a2fec
     /* Write permissions never work with read-only images */
4a2fec
     if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
4a2fec
-        !bdrv_is_writable(bs))
4a2fec
+        !bdrv_is_writable(bs, q))
4a2fec
     {
4a2fec
         error_setg(errp, "Block node is read-only");
4a2fec
         return -EPERM;
4a2fec
@@ -1862,8 +1891,7 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
4a2fec
                                   &perm, &shared);
4a2fec
 
4a2fec
         /* Format drivers may touch metadata even if the guest doesn't write */
4a2fec
-        /* TODO Take flags from reopen_queue */
4a2fec
-        if (bdrv_is_writable(bs)) {
4a2fec
+        if (bdrv_is_writable(bs, reopen_queue)) {
4a2fec
             perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
4a2fec
         }
4a2fec
 
4a2fec
@@ -2641,12 +2669,6 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
4a2fec
                              NULL, errp);
4a2fec
 }
4a2fec
 
4a2fec
-typedef struct BlockReopenQueueEntry {
4a2fec
-     bool prepared;
4a2fec
-     BDRVReopenState state;
4a2fec
-     QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry;
4a2fec
-} BlockReopenQueueEntry;
4a2fec
-
4a2fec
 /*
4a2fec
  * Adds a BlockDriverState to a simple queue for an atomic, transactional
4a2fec
  * reopen of multiple devices.
4a2fec
diff --git a/include/block/block.h b/include/block/block.h
4a2fec
index ab80195..4d0d2da 100644
4a2fec
--- a/include/block/block.h
4a2fec
+++ b/include/block/block.h
4a2fec
@@ -435,7 +435,6 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
4a2fec
                             int64_t offset, int64_t bytes, int64_t *pnum);
4a2fec
 
4a2fec
 bool bdrv_is_read_only(BlockDriverState *bs);
4a2fec
-bool bdrv_is_writable(BlockDriverState *bs);
4a2fec
 int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
4a2fec
                            bool ignore_allow_rdw, Error **errp);
4a2fec
 int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec