All of lore.kernel.org
 help / color / mirror / Atom feed
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
To: qemu-block@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Fam Zheng <fam@euphon.net>,
	qemu-devel@nongnu.org,
	Emanuele Giuseppe Esposito <eesposit@redhat.com>,
	Markus Armbruster <armbru@redhat.com>,
	Max Reitz <mreitz@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>, John Snow <jsnow@redhat.com>
Subject: [PATCH v2 7/8] block/replication: do not acquire AioContext
Date: Mon, 19 Apr 2021 10:55:40 +0200	[thread overview]
Message-ID: <20210419085541.22310-8-eesposit@redhat.com> (raw)
In-Reply-To: <20210419085541.22310-1-eesposit@redhat.com>

Replication functions are mostly called when the BDS is quiescent and
does not have any pending I/O.  They do not need to synchronize on
anything since BDS and BB are now thread-safe.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
---
 block/replication.c | 54 ++++++++++-----------------------------------
 1 file changed, 12 insertions(+), 42 deletions(-)

diff --git a/block/replication.c b/block/replication.c
index 97be7ef4de..25ee37b21b 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -45,6 +45,8 @@ typedef struct BDRVReplicationState {
     Error *blocker;
     bool orig_hidden_read_only;
     bool orig_secondary_read_only;
+
+    /* This field is accessed asynchronously.  */
     int error;
 } BDRVReplicationState;
 
@@ -210,7 +212,7 @@ static int replication_return_value(BDRVReplicationState *s, int ret)
     }
 
     if (ret < 0) {
-        s->error = ret;
+        qatomic_set(&s->error, ret);
         ret = 0;
     }
 
@@ -307,6 +309,7 @@ out:
     return ret;
 }
 
+/* Called with no I/O pending.  */
 static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
 {
     Error *local_err = NULL;
@@ -420,7 +423,7 @@ static void backup_job_completed(void *opaque, int ret)
 
     if (s->stage != BLOCK_REPLICATION_FAILOVER) {
         /* The backup job is cancelled unexpectedly */
-        s->error = -EIO;
+        qatomic_set(&s->error, -EIO);
     }
 
     backup_job_cleanup(bs);
@@ -445,6 +448,7 @@ static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
     return false;
 }
 
+/* Called with no I/O pending.  */
 static void replication_start(ReplicationState *rs, ReplicationMode mode,
                               Error **errp)
 {
@@ -452,12 +456,9 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
     BDRVReplicationState *s;
     BlockDriverState *top_bs;
     int64_t active_length, hidden_length, disk_length;
-    AioContext *aio_context;
     Error *local_err = NULL;
     BackupPerf perf = { .use_copy_range = true, .max_workers = 1 };
 
-    aio_context = bdrv_get_aio_context(bs);
-    aio_context_acquire(aio_context);
     s = bs->opaque;
 
     if (s->stage == BLOCK_REPLICATION_DONE ||
@@ -467,20 +468,17 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
          * Ignore the request because the secondary side of replication
          * doesn't have to do anything anymore.
          */
-        aio_context_release(aio_context);
         return;
     }
 
     if (s->stage != BLOCK_REPLICATION_NONE) {
         error_setg(errp, "Block replication is running or done");
-        aio_context_release(aio_context);
         return;
     }
 
     if (s->mode != mode) {
         error_setg(errp, "The parameter mode's value is invalid, needs %d,"
                    " but got %d", s->mode, mode);
-        aio_context_release(aio_context);
         return;
     }
 
@@ -492,21 +490,18 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
         if (!s->active_disk || !s->active_disk->bs ||
                                     !s->active_disk->bs->backing) {
             error_setg(errp, "Active disk doesn't have backing file");
-            aio_context_release(aio_context);
             return;
         }
 
         s->hidden_disk = s->active_disk->bs->backing;
         if (!s->hidden_disk->bs || !s->hidden_disk->bs->backing) {
             error_setg(errp, "Hidden disk doesn't have backing file");
-            aio_context_release(aio_context);
             return;
         }
 
         s->secondary_disk = s->hidden_disk->bs->backing;
         if (!s->secondary_disk->bs || !bdrv_has_blk(s->secondary_disk->bs)) {
             error_setg(errp, "The secondary disk doesn't have block backend");
-            aio_context_release(aio_context);
             return;
         }
 
@@ -518,7 +513,6 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
             active_length != hidden_length || hidden_length != disk_length) {
             error_setg(errp, "Active disk, hidden disk, secondary disk's length"
                        " are not the same");
-            aio_context_release(aio_context);
             return;
         }
 
@@ -529,7 +523,6 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
             !s->hidden_disk->bs->drv->bdrv_make_empty) {
             error_setg(errp,
                        "Active disk or hidden disk doesn't support make_empty");
-            aio_context_release(aio_context);
             return;
         }
 
@@ -537,7 +530,6 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
         reopen_backing_file(bs, true, &local_err);
         if (local_err) {
             error_propagate(errp, local_err);
-            aio_context_release(aio_context);
             return;
         }
 
@@ -550,7 +542,6 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
             !check_top_bs(top_bs, bs)) {
             error_setg(errp, "No top_bs or it is invalid");
             reopen_backing_file(bs, false, NULL);
-            aio_context_release(aio_context);
             return;
         }
         bdrv_op_block_all(top_bs, s->blocker);
@@ -566,13 +557,11 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
         if (local_err) {
             error_propagate(errp, local_err);
             backup_job_cleanup(bs);
-            aio_context_release(aio_context);
             return;
         }
         job_start(&s->backup_job->job);
         break;
     default:
-        aio_context_release(aio_context);
         abort();
     }
 
@@ -582,18 +571,15 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
         secondary_do_checkpoint(s, errp);
     }
 
-    s->error = 0;
-    aio_context_release(aio_context);
+    qatomic_set(&s->error, 0);
 }
 
+/* Called with no I/O pending.  */
 static void replication_do_checkpoint(ReplicationState *rs, Error **errp)
 {
     BlockDriverState *bs = rs->opaque;
     BDRVReplicationState *s;
-    AioContext *aio_context;
 
-    aio_context = bdrv_get_aio_context(bs);
-    aio_context_acquire(aio_context);
     s = bs->opaque;
 
     if (s->stage == BLOCK_REPLICATION_DONE ||
@@ -603,38 +589,30 @@ static void replication_do_checkpoint(ReplicationState *rs, Error **errp)
          * Ignore the request because the secondary side of replication
          * doesn't have to do anything anymore.
          */
-        aio_context_release(aio_context);
         return;
     }
 
     if (s->mode == REPLICATION_MODE_SECONDARY) {
         secondary_do_checkpoint(s, errp);
     }
-    aio_context_release(aio_context);
 }
 
 static void replication_get_error(ReplicationState *rs, Error **errp)
 {
     BlockDriverState *bs = rs->opaque;
     BDRVReplicationState *s;
-    AioContext *aio_context;
 
-    aio_context = bdrv_get_aio_context(bs);
-    aio_context_acquire(aio_context);
     s = bs->opaque;
 
     if (s->stage == BLOCK_REPLICATION_NONE) {
         error_setg(errp, "Block replication is not running");
-        aio_context_release(aio_context);
         return;
     }
 
-    if (s->error) {
+    if (qatomic_read(&s->error)) {
         error_setg(errp, "I/O error occurred");
-        aio_context_release(aio_context);
         return;
     }
-    aio_context_release(aio_context);
 }
 
 static void replication_done(void *opaque, int ret)
@@ -648,10 +626,10 @@ static void replication_done(void *opaque, int ret)
         s->active_disk = NULL;
         s->secondary_disk = NULL;
         s->hidden_disk = NULL;
-        s->error = 0;
+        qatomic_set(&s->error, 0);
     } else {
         s->stage = BLOCK_REPLICATION_FAILOVER_FAILED;
-        s->error = -EIO;
+        qatomic_set(&s->error, -EIO);
     }
 }
 
@@ -659,10 +637,7 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
 {
     BlockDriverState *bs = rs->opaque;
     BDRVReplicationState *s;
-    AioContext *aio_context;
 
-    aio_context = bdrv_get_aio_context(bs);
-    aio_context_acquire(aio_context);
     s = bs->opaque;
 
     if (s->stage == BLOCK_REPLICATION_DONE ||
@@ -672,20 +647,18 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
          * Ignore the request because the secondary side of replication
          * doesn't have to do anything anymore.
          */
-        aio_context_release(aio_context);
         return;
     }
 
     if (s->stage != BLOCK_REPLICATION_RUNNING) {
         error_setg(errp, "Block replication is not running");
-        aio_context_release(aio_context);
         return;
     }
 
     switch (s->mode) {
     case REPLICATION_MODE_PRIMARY:
         s->stage = BLOCK_REPLICATION_DONE;
-        s->error = 0;
+        qatomic_set(&s->error, 0);
         break;
     case REPLICATION_MODE_SECONDARY:
         /*
@@ -700,7 +673,6 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
         if (!failover) {
             secondary_do_checkpoint(s, errp);
             s->stage = BLOCK_REPLICATION_DONE;
-            aio_context_release(aio_context);
             return;
         }
 
@@ -711,10 +683,8 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
                             NULL, replication_done, bs, true, errp);
         break;
     default:
-        aio_context_release(aio_context);
         abort();
     }
-    aio_context_release(aio_context);
 }
 
 static const char *const replication_strong_runtime_opts[] = {
-- 
2.30.2



  parent reply	other threads:[~2021-04-19  8:59 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-19  8:55 [PATCH v2 0/8] Block layer thread-safety, continued Emanuele Giuseppe Esposito
2021-04-19  8:55 ` [PATCH v2 1/8] block: prepare write threshold code for thread safety Emanuele Giuseppe Esposito
2021-05-05  8:50   ` Stefan Hajnoczi
2021-05-05  9:54     ` Vladimir Sementsov-Ogievskiy
2021-05-06  9:04       ` Stefan Hajnoczi
2021-05-06  9:14         ` Vladimir Sementsov-Ogievskiy
2021-04-19  8:55 ` [PATCH v2 2/8] block: protect write threshold QMP commands from concurrent requests Emanuele Giuseppe Esposito
2021-05-05  8:55   ` Stefan Hajnoczi
2021-05-05 11:29     ` Paolo Bonzini
2021-04-19  8:55 ` [PATCH v2 3/8] util: use RCU accessors for notifiers Emanuele Giuseppe Esposito
2021-05-05  9:47   ` Stefan Hajnoczi
2021-04-19  8:55 ` [PATCH v2 4/8] block: make before-write notifiers thread-safe Emanuele Giuseppe Esposito
2021-04-21 21:23   ` Vladimir Sementsov-Ogievskiy
2021-04-21 22:17     ` Vladimir Sementsov-Ogievskiy
2021-04-19  8:55 ` [PATCH v2 5/8] block: add a few more notes on locking Emanuele Giuseppe Esposito
2021-05-05  9:53   ` Stefan Hajnoczi
2021-04-19  8:55 ` [PATCH v2 6/8] block: do not acquire AioContext in check_to_replace_node Emanuele Giuseppe Esposito
2021-05-05 10:10   ` Paolo Bonzini
2021-04-19  8:55 ` Emanuele Giuseppe Esposito [this message]
2021-05-05  9:57   ` [PATCH v2 7/8] block/replication: do not acquire AioContext Stefan Hajnoczi
2021-05-05 10:33   ` Paolo Bonzini
2021-04-19  8:55 ` [PATCH v2 8/8] block: do not take AioContext around reopen Emanuele Giuseppe Esposito
2021-04-21 12:24   ` Paolo Bonzini
2021-05-05 10:01   ` Stefan Hajnoczi
2021-04-21 12:25 ` [PATCH v2 0/8] Block layer thread-safety, continued Paolo Bonzini

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=20210419085541.22310-8-eesposit@redhat.com \
    --to=eesposit@redhat.com \
    --cc=armbru@redhat.com \
    --cc=fam@euphon.net \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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.