From patchwork Fri Apr 24 15:01:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Garcia X-Patchwork-Id: 464223 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C1202140134 for ; Sat, 25 Apr 2015 01:02:58 +1000 (AEST) Received: from localhost ([::1]:45205 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ylf85-0005Yz-12 for incoming@patchwork.ozlabs.org; Fri, 24 Apr 2015 11:02:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58981) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ylf7K-0004A5-CK for qemu-devel@nongnu.org; Fri, 24 Apr 2015 11:02:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ylf7E-0006Fs-1m for qemu-devel@nongnu.org; Fri, 24 Apr 2015 11:02:10 -0400 Received: from smtp3.mundo-r.com ([212.51.32.191]:51742 helo=smtp4.mundo-r.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ylf7D-0006EN-Qs; Fri, 24 Apr 2015 11:02:03 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AukFALVZOlVbdWOb/2dsb2JhbABbgwxSXLRoBAUBgQKSMYYMAoE9TAEBAQEBAYELhCEBAQQnUhBRPBsZiC8BzBoBAQEHIoYWiUBlB4QtBYtYg0mGM4Y3gSI9hXtgjRsjYIEnHIFUOzGBAoFCAQEB X-IPAS-Result: AukFALVZOlVbdWOb/2dsb2JhbABbgwxSXLRoBAUBgQKSMYYMAoE9TAEBAQEBAYELhCEBAQQnUhBRPBsZiC8BzBoBAQEHIoYWiUBlB4QtBYtYg0mGM4Y3gSI9hXtgjRsjYIEnHIFUOzGBAoFCAQEB X-IronPort-AV: E=Sophos;i="5.11,640,1422918000"; d="scan'208";a="345267694" Received: from fanzine.igalia.com ([91.117.99.155]) by smtp4.mundo-r.com with ESMTP; 24 Apr 2015 17:01:59 +0200 Received: from maestria.local.igalia.com ([192.168.10.14] helo=mail.igalia.com) by fanzine.igalia.com with esmtps (Cipher TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim) id 1Ylf79-0004vV-OQ; Fri, 24 Apr 2015 17:01:59 +0200 Received: from fanzine.local.igalia.com ([192.168.10.13] helo=perseus.local) by mail.igalia.com with esmtps (Cipher TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim) id 1Ylf78-0007GJ-Sp; Fri, 24 Apr 2015 17:01:59 +0200 Received: from berto by perseus.local with local (Exim 4.84) (envelope-from ) id 1Ylf77-0005V5-HU; Fri, 24 Apr 2015 18:01:57 +0300 From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 24 Apr 2015 18:01:48 +0300 Message-Id: <99bddcd1d44b596f58cdc429b9b757a44d3c23aa.1429885069.git.berto@igalia.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 212.51.32.191 Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi Subject: [Qemu-devel] [PATCH 04/11] block: Support streaming to an intermediate layer 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 This makes sure that the image we are steaming into is open in read-write mode during the operation. Operation blockers are also set in all intermediate nodes, since they will be removed from the chain afterwards. Finally, this also unblocks the stream operation in backing files. Signed-off-by: Alberto Garcia Reviewed-by: Max Reitz --- block.c | 4 +++- block/stream.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index 25289ef..e892cb4 100644 --- a/block.c +++ b/block.c @@ -1240,9 +1240,11 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd) backing_hd->drv ? backing_hd->drv->format_name : ""); bdrv_op_block_all(bs->backing_hd, bs->backing_blocker); - /* Otherwise we won't be able to commit due to check in bdrv_commit */ + /* Otherwise we won't be able to commit or stream */ bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT_TARGET, bs->backing_blocker); + bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_STREAM, + bs->backing_blocker); out: bdrv_refresh_limits(bs, NULL); } diff --git a/block/stream.c b/block/stream.c index 37bfd8b..8ba5a24 100644 --- a/block/stream.c +++ b/block/stream.c @@ -33,6 +33,8 @@ typedef struct StreamBlockJob { BlockDriverState *base; BlockdevOnError on_error; char *backing_file_str; + int bs_flags; + Error *blocker; } StreamBlockJob; static int coroutine_fn stream_populate(BlockDriverState *bs, @@ -89,6 +91,13 @@ static void stream_complete(BlockJob *job, void *opaque) StreamBlockJob *s = container_of(job, StreamBlockJob, common); StreamCompleteData *data = opaque; BlockDriverState *base = s->base; + BlockDriverState *bs; + + /* Remove all blockers set in stream_start() */ + for (bs = job->bs->backing_hd; bs && bs != s->base; bs = bs->backing_hd) { + bdrv_op_unblock_all(bs, s->blocker); + } + error_free(s->blocker); if (!block_job_is_cancelled(&s->common) && data->reached_end && data->ret == 0) { @@ -103,6 +112,11 @@ static void stream_complete(BlockJob *job, void *opaque) close_unused_images(job->bs, base, base_id); } + /* Reopen the image back in read-only mode if necessary */ + if (s->bs_flags != bdrv_get_flags(job->bs)) { + bdrv_reopen(job->bs, s->bs_flags, NULL); + } + g_free(s->backing_file_str); block_job_completed(&s->common, data->ret); g_free(data); @@ -246,7 +260,9 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, BlockCompletionFunc *cb, void *opaque, Error **errp) { + BlockDriverState *iter; StreamBlockJob *s; + int orig_bs_flags; if ((on_error == BLOCKDEV_ON_ERROR_STOP || on_error == BLOCKDEV_ON_ERROR_ENOSPC) && @@ -255,13 +271,30 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, return; } + /* Make sure that the image is opened in read-write mode */ + orig_bs_flags = bdrv_get_flags(bs); + if (!(orig_bs_flags & BDRV_O_RDWR)) { + if (bdrv_reopen(bs, orig_bs_flags | BDRV_O_RDWR, errp) != 0) { + return; + } + } + s = block_job_create(&stream_job_driver, bs, speed, cb, opaque, errp); if (!s) { return; } + /* Block all intermediate nodes between bs and base, because they + * will disappear from the chain after this operation */ + error_setg(&s->blocker, "blocked by the block-stream operation in '%s'", + bdrv_get_device_or_node_name(bs)); + for (iter = bs->backing_hd; iter && iter != base; iter = iter->backing_hd) { + bdrv_op_block_all(iter, s->blocker); + } + s->base = base; s->backing_file_str = g_strdup(backing_file_str); + s->bs_flags = orig_bs_flags; s->on_error = on_error; s->common.co = qemu_coroutine_create(stream_run);