All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [PULL 14/28] block: Mark bdrv_get_cumulative_perm() and callers GRAPH_RDLOCK
Date: Fri, 15 Sep 2023 16:43:30 +0200	[thread overview]
Message-ID: <20230915144344.238596-15-kwolf@redhat.com> (raw)
In-Reply-To: <20230915144344.238596-1-kwolf@redhat.com>

The function reads the parents list, so it needs to hold the graph lock.

This happens to result in BlockDriver.bdrv_set_perm() to be called with
the graph lock held. For consistency, make it the same for all of the
BlockDriver callbacks for updating permissions and annotate the function
pointers with GRAPH_RDLOCK_PTR.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20230911094620.45040-15-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block_int-common.h       |  9 ++++---
 include/block/block_int-global-state.h |  4 +--
 block.c                                | 35 ++++++++++++++++++++------
 blockdev.c                             |  6 +++++
 4 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index fda9d8b5c8..f82c14fb9c 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -413,8 +413,8 @@ struct BlockDriver {
      * If both conditions are met, 0 is returned. Otherwise, -errno is returned
      * and errp is set to an error describing the conflict.
      */
-    int (*bdrv_check_perm)(BlockDriverState *bs, uint64_t perm,
-                           uint64_t shared, Error **errp);
+    int GRAPH_RDLOCK_PTR (*bdrv_check_perm)(BlockDriverState *bs, uint64_t perm,
+                                            uint64_t shared, Error **errp);
 
     /**
      * Called to inform the driver that the set of cumulative set of used
@@ -426,7 +426,8 @@ struct BlockDriver {
      * This function is only invoked after bdrv_check_perm(), so block drivers
      * may rely on preparations made in their .bdrv_check_perm implementation.
      */
-    void (*bdrv_set_perm)(BlockDriverState *bs, uint64_t perm, uint64_t shared);
+    void GRAPH_RDLOCK_PTR (*bdrv_set_perm)(
+        BlockDriverState *bs, uint64_t perm, uint64_t shared);
 
     /*
      * Called to inform the driver that after a previous bdrv_check_perm()
@@ -436,7 +437,7 @@ struct BlockDriver {
      * This function can be called even for nodes that never saw a
      * bdrv_check_perm() call. It is a no-op then.
      */
-    void (*bdrv_abort_perm_update)(BlockDriverState *bs);
+    void GRAPH_RDLOCK_PTR (*bdrv_abort_perm_update)(BlockDriverState *bs);
 
     /**
      * Returns in @nperm and @nshared the permissions that the driver for @bs
diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h
index bebcc08bce..e2304db58b 100644
--- a/include/block/block_int-global-state.h
+++ b/include/block/block_int-global-state.h
@@ -204,8 +204,8 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
                                   void *opaque, Error **errp);
 void bdrv_root_unref_child(BdrvChild *child);
 
-void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
-                              uint64_t *shared_perm);
+void GRAPH_RDLOCK bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
+                                           uint64_t *shared_perm);
 
 /**
  * Sets a BdrvChild's permissions.  Avoid if the parent is a BDS; use
diff --git a/block.c b/block.c
index 6720bc4f8a..186efda70f 100644
--- a/block.c
+++ b/block.c
@@ -2320,7 +2320,7 @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm,
     tran_add(tran, &bdrv_child_set_pem_drv, s);
 }
 
-static void bdrv_drv_set_perm_commit(void *opaque)
+static void GRAPH_RDLOCK bdrv_drv_set_perm_commit(void *opaque)
 {
     BlockDriverState *bs = opaque;
     uint64_t cumulative_perms, cumulative_shared_perms;
@@ -2333,7 +2333,7 @@ static void bdrv_drv_set_perm_commit(void *opaque)
     }
 }
 
-static void bdrv_drv_set_perm_abort(void *opaque)
+static void GRAPH_RDLOCK bdrv_drv_set_perm_abort(void *opaque)
 {
     BlockDriverState *bs = opaque;
     GLOBAL_STATE_CODE();
@@ -2348,9 +2348,13 @@ TransactionActionDrv bdrv_drv_set_perm_drv = {
     .commit = bdrv_drv_set_perm_commit,
 };
 
-static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm,
-                             uint64_t shared_perm, Transaction *tran,
-                             Error **errp)
+/*
+ * After calling this function, the transaction @tran may only be completed
+ * while holding a reader lock for the graph.
+ */
+static int GRAPH_RDLOCK
+bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared_perm,
+                  Transaction *tran, Error **errp)
 {
     GLOBAL_STATE_CODE();
     if (!bs->drv) {
@@ -2457,9 +2461,13 @@ bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
 /*
  * Refresh permissions in @bs subtree. The function is intended to be called
  * after some graph modification that was done without permission update.
+ *
+ * After calling this function, the transaction @tran may only be completed
+ * while holding a reader lock for the graph.
  */
-static int bdrv_node_refresh_perm(BlockDriverState *bs, BlockReopenQueue *q,
-                                  Transaction *tran, Error **errp)
+static int GRAPH_RDLOCK
+bdrv_node_refresh_perm(BlockDriverState *bs, BlockReopenQueue *q,
+                       Transaction *tran, Error **errp)
 {
     BlockDriver *drv = bs->drv;
     BdrvChild *c;
@@ -2532,6 +2540,9 @@ static int bdrv_node_refresh_perm(BlockDriverState *bs, BlockReopenQueue *q,
 /*
  * @list is a product of bdrv_topological_dfs() (may be called several times) -
  * a topologically sorted subgraph.
+ *
+ * After calling this function, the transaction @tran may only be completed
+ * while holding a reader lock for the graph.
  */
 static int GRAPH_RDLOCK
 bdrv_do_refresh_perms(GSList *list, BlockReopenQueue *q, Transaction *tran,
@@ -2561,6 +2572,9 @@ bdrv_do_refresh_perms(GSList *list, BlockReopenQueue *q, Transaction *tran,
  * @list is any list of nodes. List is completed by all subtrees and
  * topologically sorted. It's not a problem if some node occurs in the @list
  * several times.
+ *
+ * After calling this function, the transaction @tran may only be completed
+ * while holding a reader lock for the graph.
  */
 static int GRAPH_RDLOCK
 bdrv_list_refresh_perms(GSList *list, BlockReopenQueue *q, Transaction *tran,
@@ -2623,7 +2637,12 @@ char *bdrv_perm_names(uint64_t perm)
 }
 
 
-/* @tran is allowed to be NULL. In this case no rollback is possible */
+/*
+ * @tran is allowed to be NULL. In this case no rollback is possible.
+ *
+ * After calling this function, the transaction @tran may only be completed
+ * while holding a reader lock for the graph.
+ */
 static int GRAPH_RDLOCK
 bdrv_refresh_perms(BlockDriverState *bs, Transaction *tran, Error **errp)
 {
diff --git a/blockdev.c b/blockdev.c
index e6eba61484..372eaf198c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1378,6 +1378,9 @@ static void external_snapshot_action(TransactionAction *action,
     AioContext *aio_context;
     uint64_t perm, shared;
 
+    /* TODO We'll eventually have to take a writer lock in this function */
+    GRAPH_RDLOCK_GUARD_MAINLOOP();
+
     tran_add(tran, &external_snapshot_drv, state);
 
     /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
@@ -2521,6 +2524,9 @@ void qmp_block_commit(const char *job_id, const char *device,
     int job_flags = JOB_DEFAULT;
     uint64_t top_perm, top_shared;
 
+    /* TODO We'll eventually have to take a writer lock in this function */
+    GRAPH_RDLOCK_GUARD_MAINLOOP();
+
     if (!has_speed) {
         speed = 0;
     }
-- 
2.41.0



  parent reply	other threads:[~2023-09-15 14:48 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-15 14:43 [PULL 00/28] Block layer patches Kevin Wolf
2023-09-15 14:43 ` [PULL 01/28] block: Remove unused BlockReopenQueueEntry.perms_checked Kevin Wolf
2023-09-15 14:43 ` [PULL 02/28] preallocate: Factor out preallocate_truncate_to_real_size() Kevin Wolf
2023-09-15 14:43 ` [PULL 03/28] preallocate: Don't poll during permission updates Kevin Wolf
2023-09-15 14:43 ` [PULL 04/28] block: Take AioContext lock for bdrv_append() more consistently Kevin Wolf
2023-09-15 14:43 ` [PULL 05/28] block: Introduce bdrv_schedule_unref() Kevin Wolf
2023-09-15 14:43 ` [PULL 06/28] block-coroutine-wrapper: Add no_co_wrapper_bdrv_wrlock functions Kevin Wolf
2023-09-15 14:43 ` [PULL 07/28] block-coroutine-wrapper: Allow arbitrary parameter names Kevin Wolf
2023-09-15 14:43 ` [PULL 08/28] block: Mark bdrv_replace_child_noperm() GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 09/28] block: Mark bdrv_replace_child_tran() GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 10/28] block: Mark bdrv_attach_child_common() GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 11/28] block: Call transaction callbacks with lock held Kevin Wolf
2023-09-15 14:43 ` [PULL 12/28] block: Mark bdrv_attach_child() GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 13/28] block: Mark bdrv_parent_perms_conflict() and callers GRAPH_RDLOCK Kevin Wolf
2023-09-15 14:43 ` Kevin Wolf [this message]
2023-09-15 14:43 ` [PULL 15/28] block: Mark bdrv_child_perm() GRAPH_RDLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 16/28] block: Mark bdrv_parent_cb_change_media() GRAPH_RDLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 17/28] block: Take graph rdlock in bdrv_drop_intermediate() Kevin Wolf
2023-09-15 14:43 ` [PULL 18/28] block: Take graph rdlock in bdrv_change_aio_context() Kevin Wolf
2023-09-15 14:43 ` [PULL 19/28] block: Mark bdrv_root_unref_child() GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 20/28] block: Mark bdrv_unref_child() GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 21/28] block: Mark bdrv_add/del_child() and caller GRAPH_WRLOCK Kevin Wolf
2023-09-15 14:43 ` [PULL 22/28] block: add BDRV_BLOCK_COMPRESSED flag for bdrv_block_status() Kevin Wolf
2023-09-15 14:43 ` [PULL 23/28] qemu-img: map: report compressed data blocks Kevin Wolf
2023-09-15 14:43 ` [PULL 24/28] block: remove AIOCBInfo->get_aio_context() Kevin Wolf
2023-09-15 14:43 ` [PULL 25/28] test-bdrv-drain: avoid race with BH in IOThread drain test Kevin Wolf
2023-09-15 14:43 ` [PULL 26/28] block-backend: process I/O in the current AioContext Kevin Wolf
2023-09-15 14:43 ` [PULL 27/28] block-backend: process zoned requests " Kevin Wolf
2023-09-15 14:43 ` [PULL 28/28] block-coroutine-wrapper: use qemu_get_current_aio_context() Kevin Wolf
2023-09-18 15:03 ` [PULL 00/28] Block layer patches Stefan Hajnoczi
2023-09-18 18:56   ` Stefan Hajnoczi
2023-09-19 10:26     ` Kevin Wolf
2023-09-19 17:35       ` Stefan Hajnoczi
2023-09-19 19:34       ` Stefan Hajnoczi
2023-09-19 20:08       ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230915144344.238596-15-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.