summary refs log tree commit diff stats
path: root/block/commit.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2023-11-09 08:26:01 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2023-11-09 08:26:01 +0800
commitad6ef0a42e314a8c6ac6c96d5f6e607a1e5644b5 (patch)
tree008e25b9b0c44a038217ee9fef33455b50d0deb4 /block/commit.c
parent9a4750143cefeee18727f2c5ede5b6a4ad80ff01 (diff)
parentb523a3d54f3d031a54cd0931cc5d855608e63140 (diff)
downloadfocaccia-qemu-ad6ef0a42e314a8c6ac6c96d5f6e607a1e5644b5.tar.gz
focaccia-qemu-ad6ef0a42e314a8c6ac6c96d5f6e607a1e5644b5.zip
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
Block layer patches

- Graph locking part 6 (bs->file/backing)
- ahci: trigger either error IRQ or regular IRQ, not both

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmVLvccRHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9ZkFg//awQoPiGnYzHpqcx2tGCM2AqBV+mFkbZr
# BKI5vp8FYfJtgMuHjC8jabL24NRMPpT+HbCzoxwjJU+nnnr85qr7R5iGwG6kfgX6
# HJlAXYXdY6e7l+FV44PBJ52vOoGCsh1GHg8HlKsHMaxSdXi9C1axHJ6rCAjnWXE0
# FQ4znCBVs/9HiKsvu4Wdm5muX2ShftFRM/toAwA+fLEOealX8WEXoRFJXI40bYbR
# OR7aJXWMDQrljlqdKk2FXvK337/tpofXmXf3NIE1R2pmY4x5Fg8bfChZn4UaaCdN
# n+0AhmE4ScI0rXuaXXYOvTO9vdTzXeBROG6tX03t9rrQfB6wPcGVeXRo/uusslAW
# sDH8NLz7uHFOooV02Fs8CKDdVrNNw5qjziclSGa0Po7vqOV1TKI8OTiNpsDLmdI5
# +DQvC6N+IU1pSOXImATSHkheGWggsegrsgN6PdrlzHEXJwWoAaRD0T06MRn74/pL
# gCegK2ez4RJYsci7C5b0gaqY/QBsMj8EUfEGVHvVyuVSoPRwiq4ehPqSQ+siA3xP
# KxYR0e4+QIfRmxqCzaJhiQ3DDGdt8UcO3yF0XcKXEqWwgFAGQKNeUG314jginvmA
# iaJzC0dHbiGcagAk7Ey8iyzfxQDWM6ixzJtGv7VLILepzCuu8vaJXy5qeEtTM/ZI
# EXoDGceNSvw=
# =ikBW
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 09 Nov 2023 00:56:39 HKT
# gpg:                using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg:                issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (25 commits)
  hw/ide/ahci: trigger either error IRQ or regular IRQ, not both
  block: Protect bs->file with graph_lock
  block: Take graph lock for most of .bdrv_open
  vhdx: Take locks for accessing bs->file
  qcow2: Take locks for accessing bs->file
  block: Add missing GRAPH_RDLOCK annotations
  block: Introduce bdrv_co_change_backing_file()
  blkverify: Add locking for request_fn
  block: Protect bs->backing with graph_lock
  block: Mark bdrv_replace_node() GRAPH_WRLOCK
  block: Mark bdrv_replace_node_common() GRAPH_WRLOCK
  block: Inline bdrv_set_backing_noperm()
  block: Mark bdrv_set_backing_hd_drained() GRAPH_WRLOCK
  block: Mark bdrv_cow_child() and callers GRAPH_RDLOCK
  block: Mark bdrv_filter_child() and callers GRAPH_RDLOCK
  block: Mark bdrv_chain_contains() and callers GRAPH_RDLOCK
  block: Mark bdrv_(un)freeze_backing_chain() and callers GRAPH_RDLOCK
  block: Mark bdrv_skip_filters() and callers GRAPH_RDLOCK
  block: Mark bdrv_skip_implicit_filters() and callers GRAPH_RDLOCK
  block: Mark bdrv_filter_or_cow_bs() and callers GRAPH_RDLOCK
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/commit.c')
-rw-r--r--block/commit.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/block/commit.c b/block/commit.c
index 43d1de7577..eb3dc01f45 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -48,8 +48,10 @@ static int commit_prepare(Job *job)
 {
     CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
 
+    bdrv_graph_rdlock_main_loop();
     bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
     s->chain_frozen = false;
+    bdrv_graph_rdunlock_main_loop();
 
     /* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before
      * the normal backing chain can be restored. */
@@ -66,9 +68,12 @@ static void commit_abort(Job *job)
 {
     CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
     BlockDriverState *top_bs = blk_bs(s->top);
+    BlockDriverState *commit_top_backing_bs;
 
     if (s->chain_frozen) {
+        bdrv_graph_rdlock_main_loop();
         bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
+        bdrv_graph_rdunlock_main_loop();
     }
 
     /* Make sure commit_top_bs and top stay around until bdrv_replace_node() */
@@ -90,8 +95,15 @@ static void commit_abort(Job *job)
      * XXX Can (or should) we somehow keep 'consistent read' blocked even
      * after the failed/cancelled commit job is gone? If we already wrote
      * something to base, the intermediate images aren't valid any more. */
-    bdrv_replace_node(s->commit_top_bs, s->commit_top_bs->backing->bs,
-                      &error_abort);
+    bdrv_graph_rdlock_main_loop();
+    commit_top_backing_bs = s->commit_top_bs->backing->bs;
+    bdrv_graph_rdunlock_main_loop();
+
+    bdrv_drained_begin(commit_top_backing_bs);
+    bdrv_graph_wrlock(commit_top_backing_bs);
+    bdrv_replace_node(s->commit_top_bs, commit_top_backing_bs, &error_abort);
+    bdrv_graph_wrunlock();
+    bdrv_drained_end(commit_top_backing_bs);
 
     bdrv_unref(s->commit_top_bs);
     bdrv_unref(top_bs);
@@ -210,7 +222,7 @@ bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
     return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
 }
 
-static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
+static GRAPH_RDLOCK void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
 {
     pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
             bs->backing->bs->filename);
@@ -255,10 +267,13 @@ void commit_start(const char *job_id, BlockDriverState *bs,
     GLOBAL_STATE_CODE();
 
     assert(top != bs);
+    bdrv_graph_rdlock_main_loop();
     if (bdrv_skip_filters(top) == bdrv_skip_filters(base)) {
         error_setg(errp, "Invalid files for merge: top and base are the same");
+        bdrv_graph_rdunlock_main_loop();
         return;
     }
+    bdrv_graph_rdunlock_main_loop();
 
     base_size = bdrv_getlength(base);
     if (base_size < 0) {
@@ -324,6 +339,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
      * this is the responsibility of the interface (i.e. whoever calls
      * commit_start()).
      */
+    bdrv_graph_wrlock(top);
     s->base_overlay = bdrv_find_overlay(top, base);
     assert(s->base_overlay);
 
@@ -354,16 +370,20 @@ void commit_start(const char *job_id, BlockDriverState *bs,
         ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
                                  iter_shared_perms, errp);
         if (ret < 0) {
+            bdrv_graph_wrunlock();
             goto fail;
         }
     }
 
     if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
+        bdrv_graph_wrunlock();
         goto fail;
     }
     s->chain_frozen = true;
 
     ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
+    bdrv_graph_wrunlock();
+
     if (ret < 0) {
         goto fail;
     }
@@ -396,7 +416,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 
 fail:
     if (s->chain_frozen) {
+        bdrv_graph_rdlock_main_loop();
         bdrv_unfreeze_backing_chain(commit_top_bs, base);
+        bdrv_graph_rdunlock_main_loop();
     }
     if (s->base) {
         blk_unref(s->base);
@@ -411,7 +433,11 @@ fail:
     /* commit_top_bs has to be replaced after deleting the block job,
      * otherwise this would fail because of lack of permissions. */
     if (commit_top_bs) {
+        bdrv_drained_begin(top);
+        bdrv_graph_wrlock(top);
         bdrv_replace_node(commit_top_bs, top, &error_abort);
+        bdrv_graph_wrunlock();
+        bdrv_drained_end(top);
     }
 }