Blame SOURCES/kvm-block-Make-permission-changes-in-reopen-less-wrong.patch

383d26
From f64042620963059859d0bbae60e8655ccc44736e Mon Sep 17 00:00:00 2001
383d26
From: Kevin Wolf <kwolf@redhat.com>
383d26
Date: Fri, 15 Mar 2019 18:10:01 +0100
383d26
Subject: [PATCH 005/163] block: Make permission changes in reopen less wrong
383d26
383d26
RH-Author: Kevin Wolf <kwolf@redhat.com>
383d26
Message-id: <20190315181010.14964-6-kwolf@redhat.com>
383d26
Patchwork-id: 84882
383d26
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 05/14] block: Make permission changes in reopen less wrong
383d26
Bugzilla: 1685989
383d26
RH-Acked-by: John Snow <jsnow@redhat.com>
383d26
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
383d26
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
383d26
The way that reopen interacts with permission changes has one big
383d26
problem: Both operations are recursive, and the permissions are changes
383d26
for each node in the reopen queue.
383d26
383d26
For a simple graph that consists just of parent and child,
383d26
.bdrv_check_perm will be called twice for the child, once recursively
383d26
when adjusting the permissions of parent, and once again when the child
383d26
itself is reopened.
383d26
383d26
Even worse, the first .bdrv_check_perm call happens before
383d26
.bdrv_reopen_prepare was called for the child and the second one is
383d26
called afterwards.
383d26
383d26
Making sure that .bdrv_check_perm (and the other permission callbacks)
383d26
are called only once is hard. We can cope with multiple calls right now,
383d26
but as soon as file-posix gets a dynamic auto-read-only that may need to
383d26
open a new file descriptor, we get the additional requirement that all
383d26
of them are after the .bdrv_reopen_prepare call.
383d26
383d26
So reorder things in bdrv_reopen_multiple() to first call
383d26
.bdrv_reopen_prepare for all involved nodes and only then adjust
383d26
permissions.
383d26
383d26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
383d26
(cherry picked from commit 69b736e76567ecbc9b9e55570bc0afc840614a98)
383d26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
383d26
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
---
383d26
 block.c | 35 ++++++++++++++++++++++++-----------
383d26
 1 file changed, 24 insertions(+), 11 deletions(-)
383d26
383d26
diff --git a/block.c b/block.c
383d26
index 2f1b4d1..b31124c 100644
383d26
--- a/block.c
383d26
+++ b/block.c
383d26
@@ -1661,6 +1661,7 @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
383d26
 
383d26
 typedef struct BlockReopenQueueEntry {
383d26
      bool prepared;
383d26
+     bool perms_checked;
383d26
      BDRVReopenState state;
383d26
      QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry;
383d26
 } BlockReopenQueueEntry;
383d26
@@ -3072,6 +3073,16 @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
383d26
         bs_entry->prepared = true;
383d26
     }
383d26
 
383d26
+    QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
383d26
+        BDRVReopenState *state = &bs_entry->state;
383d26
+        ret = bdrv_check_perm(state->bs, bs_queue, state->perm,
383d26
+                              state->shared_perm, NULL, errp);
383d26
+        if (ret < 0) {
383d26
+            goto cleanup_perm;
383d26
+        }
383d26
+        bs_entry->perms_checked = true;
383d26
+    }
383d26
+
383d26
     /* If we reach this point, we have success and just need to apply the
383d26
      * changes
383d26
      */
383d26
@@ -3080,7 +3091,20 @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
383d26
     }
383d26
 
383d26
     ret = 0;
383d26
+cleanup_perm:
383d26
+    QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
383d26
+        BDRVReopenState *state = &bs_entry->state;
383d26
+
383d26
+        if (!bs_entry->perms_checked) {
383d26
+            continue;
383d26
+        }
383d26
 
383d26
+        if (ret == 0) {
383d26
+            bdrv_set_perm(state->bs, state->perm, state->shared_perm);
383d26
+        } else {
383d26
+            bdrv_abort_perm_update(state->bs);
383d26
+        }
383d26
+    }
383d26
 cleanup:
383d26
     QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
383d26
         if (ret) {
383d26
@@ -3297,12 +3321,6 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
383d26
         } while ((entry = qdict_next(reopen_state->options, entry)));
383d26
     }
383d26
 
383d26
-    ret = bdrv_check_perm(reopen_state->bs, queue, reopen_state->perm,
383d26
-                          reopen_state->shared_perm, NULL, errp);
383d26
-    if (ret < 0) {
383d26
-        goto error;
383d26
-    }
383d26
-
383d26
     ret = 0;
383d26
 
383d26
 error:
383d26
@@ -3352,9 +3370,6 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
383d26
 
383d26
     bdrv_refresh_limits(bs, NULL);
383d26
 
383d26
-    bdrv_set_perm(reopen_state->bs, reopen_state->perm,
383d26
-                  reopen_state->shared_perm);
383d26
-
383d26
     new_can_write =
383d26
         !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
383d26
     if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) {
383d26
@@ -3386,8 +3401,6 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
383d26
     if (drv->bdrv_reopen_abort) {
383d26
         drv->bdrv_reopen_abort(reopen_state);
383d26
     }
383d26
-
383d26
-    bdrv_abort_perm_update(reopen_state->bs);
383d26
 }
383d26
 
383d26
 
383d26
-- 
383d26
1.8.3.1
383d26