[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH untested] mirror: start drained section earlier
From: |
Fam Zheng |
Subject: |
Re: [Qemu-devel] [PATCH untested] mirror: start drained section earlier |
Date: |
Thu, 17 Dec 2015 10:14:44 +0800 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Wed, 12/16 19:33, Paolo Bonzini wrote:
> Ensure that the guest does not write anything to disk after cnt is
> read for the final time.
>
> Signed-off-by: Paolo Bonzini <address@hidden>
> ---
> Untested.
>
> block/mirror.c | 22 +++++++++++-----------
> 1 file changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/block/mirror.c b/block/mirror.c
> index 0e8f556..e57c246 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -562,8 +562,18 @@ static void coroutine_fn mirror_run(void *opaque)
> * mirror_populate runs.
> */
> trace_mirror_before_drain(s, cnt);
> - bdrv_drain(bs);
> + bdrv_drained_begin(s->common.bs);
> cnt = bdrv_get_dirty_count(s->dirty_bitmap);
> +
> + if (cnt == 0) {
> + /* The two disks are in sync. Exit and report successful
> + * completion.
> + */
> + assert(QLIST_EMPTY(&bs->tracked_requests));
> + s->common.cancelled = false;
> + break;
> + }
> + bdrv_drained_end(s->common.bs);
> }
>
> ret = 0;
> @@ -576,13 +586,6 @@ static void coroutine_fn mirror_run(void *opaque)
> } else if (!should_complete) {
> delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);
> block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
> - } else if (cnt == 0) {
> - /* The two disks are in sync. Exit and report successful
> - * completion.
> - */
> - assert(QLIST_EMPTY(&bs->tracked_requests));
> - s->common.cancelled = false;
> - break;
> }
> last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
> }
> @@ -608,9 +611,6 @@ immediate_exit:
>
> data = g_malloc(sizeof(*data));
> data->ret = ret;
> - /* Before we switch to target in mirror_exit, make sure data doesn't
> - * change. */
> - bdrv_drained_begin(s->common.bs);
> block_job_defer_to_main_loop(&s->common, mirror_exit, data);
> }
bdrv_drained_begin was unconditional to balance with the one in mirror_exit,
but now it is only called if cnt == 0. Squashing this in fixes it:
diff --git a/block/mirror.c b/block/mirror.c
index e57c246..a814929 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -62,6 +62,7 @@ typedef struct MirrorBlockJob {
int ret;
bool unmap;
bool waiting_for_io;
+ bool drained_begin;
} MirrorBlockJob;
typedef struct MirrorOp {
@@ -355,6 +356,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
MirrorExitData *data = opaque;
AioContext *replace_aio_context = NULL;
BlockDriverState *src = s->common.bs;
+ bool drained_begin = s->drained_begin;
/* Make sure that the source BDS doesn't go away before we called
* block_job_completed(). */
@@ -388,7 +390,9 @@ static void mirror_exit(BlockJob *job, void *opaque)
bdrv_unref(s->target);
block_job_completed(&s->common, data->ret);
g_free(data);
- bdrv_drained_end(src);
+ if (drained_begin) {
+ bdrv_drained_end(src);
+ }
bdrv_unref(src);
}
@@ -571,6 +575,7 @@ static void coroutine_fn mirror_run(void *opaque)
*/
assert(QLIST_EMPTY(&bs->tracked_requests));
s->common.cancelled = false;
+ s->drained_begin = true;
break;
}
bdrv_drained_end(s->common.bs);