From patchwork Tue Jul 24 11:04:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 172856 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3FA9D2C008F for ; Tue, 24 Jul 2012 22:09:50 +1000 (EST) Received: from localhost ([::1]:36374 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Stdvw-0003b8-8D for incoming@patchwork.ozlabs.org; Tue, 24 Jul 2012 08:09:48 -0400 Received: from eggs.gnu.org ([208.118.235.92]:56900) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1StcwP-0007rl-1w for qemu-devel@nongnu.org; Tue, 24 Jul 2012 07:06:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1StcwI-0005qH-TO for qemu-devel@nongnu.org; Tue, 24 Jul 2012 07:06:12 -0400 Received: from mail-gh0-f173.google.com ([209.85.160.173]:59147) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1StcwI-0005Rh-PH for qemu-devel@nongnu.org; Tue, 24 Jul 2012 07:06:06 -0400 Received: by mail-gh0-f173.google.com with SMTP id r14so6581704ghr.4 for ; Tue, 24 Jul 2012 04:06:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=6992bxCT+ob/7WGMOHODoxKt2QnaKX9gx2PvbULmUjs=; b=BU8QQBhAR/hoiurXF3nJd/A3wAh9bqv/VbaAg0nsFr5NNjtVe2JfrLQ1BdZrPdmV6N +PcKA3sybVUm8BbYOj2BHx71Ko/UqBBcqbbVW//r1mzzOba8j26McVtafriRjz5k9Vei 6apE0YKgMAGekUdXO/5RiWMibEobP0br1hKFrQE1kFv9kkF8KIJyl59zAFTcjofWQj1y AMOsH9eR5VUyc6ClSB10p+FxzaOUzZZBred0XmzLGVRWEkzuPVi3RNljs7ggZN4vJKii sPyspl8RQKUXeJFfQa5vUZXbjcOMbYw7SLYfZLfFrQOH1A8Jk1Z89MNTYCdqni34IAOE kRGg== Received: by 10.43.46.194 with SMTP id up2mr14600958icb.22.1343127966466; Tue, 24 Jul 2012 04:06:06 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-189-113.ip51.fastwebnet.it. [93.34.189.113]) by mx.google.com with ESMTPS id if4sm1752561igc.10.2012.07.24.04.06.03 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 24 Jul 2012 04:06:05 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 24 Jul 2012 13:04:08 +0200 Message-Id: <1343127865-16608-31-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1343127865-16608-1-git-send-email-pbonzini@redhat.com> References: <1343127865-16608-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.160.173 Cc: kwolf@redhat.com, jcody@redhat.com, eblake@redhat.com, stefanha@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 30/47] mirror: implement completion X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Switching to the target of the migration is done mostly asynchronously, and reported to management via the BLOCK_JOB_COMPLETED event; the only synchronous phase is opening the backing files. Note that this can be done always, even for migration of the full image, because the backing file structure of the source and target are not in any relationship. For full migration (aka sync: 'full') qmp_drive_mirror will create the target disk with no backing file at all, and bdrv_ensure_backing_file will be a no-op. Signed-off-by: Paolo Bonzini --- block/mirror.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 9c8ebd4..4454ef3 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -32,6 +32,8 @@ typedef struct MirrorBlockJob { RateLimit limit; BlockDriverState *target; MirrorSyncMode mode; + bool synced; + bool complete; int64_t sector_num; uint8_t *buf; } MirrorBlockJob; @@ -70,7 +72,6 @@ static void coroutine_fn mirror_run(void *opaque) int64_t sector_num, end; int ret = 0; int n; - bool synced = false; if (block_job_is_cancelled(&s->common)) { goto immediate_exit; @@ -135,10 +136,13 @@ static void coroutine_fn mirror_run(void *opaque) * I/O and report completion, so that drive-reopen can be * used to pivot to the mirroring target. */ - synced = true; s->common.offset = end * BDRV_SECTOR_SIZE; + if (!s->synced) { + block_job_ready(&s->common); + s->synced = true; + } - should_complete = block_job_is_cancelled(&s->common); + should_complete = block_job_is_cancelled(&s->common) || s->complete; if (should_complete) { /* The dirty bitmap is not updated while operations are pending. * If we're about to exit, wait for pending operations before @@ -155,8 +159,8 @@ static void coroutine_fn mirror_run(void *opaque) } ret = 0; - trace_mirror_before_sleep(s, cnt, synced); - if (!synced) { + trace_mirror_before_sleep(s, cnt, s->synced); + if (!s->synced) { /* Publish progress */ s->common.offset = end * BDRV_SECTOR_SIZE - cnt * BLOCK_SIZE; @@ -189,7 +193,11 @@ static void coroutine_fn mirror_run(void *opaque) immediate_exit: g_free(s->buf); bdrv_set_dirty_tracking(bs, false); - bdrv_close(s->target); + if (s->complete && ret == 0) { + bdrv_swap(s->target, s->common.bs); + } else { + bdrv_close(s->target); + } bdrv_delete(s->target); block_job_completed(&s->common, ret); } @@ -215,11 +223,34 @@ static void mirror_query(BlockJob *job, BlockJobInfo *info) info->target->stats = bdrv_query_stats(s->target); } +static void mirror_complete(BlockJob *job, Error **errp) +{ + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); + int ret; + + ret = bdrv_ensure_backing_file(s->target); + if (ret < 0) { + char backing_filename[PATH_MAX]; + bdrv_get_full_backing_filename(s->target, backing_filename, + sizeof(backing_filename)); + error_set(errp, QERR_OPEN_FILE_FAILED, backing_filename); + return; + } + if (!s->synced) { + error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name); + return; + } + + s->complete = true; + block_job_resume(job); +} + static BlockJobType mirror_job_type = { .instance_size = sizeof(MirrorBlockJob), .job_type = "mirror", .set_speed = mirror_set_speed, .query = mirror_query, + .complete = mirror_complete, }; void mirror_start(BlockDriverState *bs, BlockDriverState *target,