From patchwork Wed Apr 29 11:15:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 283798 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D04D3C83003 for ; Wed, 29 Apr 2020 11:20:35 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9CD6E206B8 for ; Wed, 29 Apr 2020 11:20:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Xby8GZYG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9CD6E206B8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43264 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jTklW-0006LE-Nr for qemu-devel@archiver.kernel.org; Wed, 29 Apr 2020 07:20:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47022) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jTkil-00059e-1u for qemu-devel@nongnu.org; Wed, 29 Apr 2020 07:19:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.90_1) (envelope-from ) id 1jTkh2-0005rP-4K for qemu-devel@nongnu.org; Wed, 29 Apr 2020 07:17:42 -0400 Received: from us-smtp-1.mimecast.com ([207.211.31.81]:44553 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1jTkh1-0005r3-NH for qemu-devel@nongnu.org; Wed, 29 Apr 2020 07:15:55 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1588158955; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bZPsVCSXiV9p7JDzxiy0Y5sACwWktPtXil+AUGleyGs=; b=Xby8GZYGTqQUEl2PSSRGp9nmJvBLvEWXf/0AwsRU0yhLy7zAevH+u9BEquTm4ReBsZrst0 YiMg8q51cNYX5jWXSl/RFtwTc7EPmKHGJgeR2rLjJoEci9SvlN0izkdPlCfv1lWgGGeiwo vv14rB2ysctAccNJUCa56bzTL8rh/ko= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-429-oiRou9xHMBOxIFfZGxUz8Q-1; Wed, 29 Apr 2020 07:15:53 -0400 X-MC-Unique: oiRou9xHMBOxIFfZGxUz8Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 39F821800D4A; Wed, 29 Apr 2020 11:15:52 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTP id B0F9460BF4; Wed, 29 Apr 2020 11:15:50 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Subject: [PATCH 2/3] backup: Make sure that source and target size match Date: Wed, 29 Apr 2020 13:15:38 +0200 Message-Id: <20200429111539.42103-3-kwolf@redhat.com> In-Reply-To: <20200429111539.42103-1-kwolf@redhat.com> References: <20200429111539.42103-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.81; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/04/29 01:28:11 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.81 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, qemu-devel@nongnu.org, mreitz@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Since the introduction of a backup filter node, the backup block job crashes when the target image is smaller than the source image because it will try to write after the end of the target node without having BLK_PERM_RESIZE. (Previously, the BlockBackend layer would have caught this and errored out gracefully.) We can fix this and even do better than the old behaviour: Check that source and target have the same image size at the start of the block job and unshare BLK_PERM_RESIZE. This will immediately error out when starting the job instead of only when writing to a block that doesn't exist in the target. Longer target than source would technically work because we would never write to blocks that don't exist, but semantically these are invalid, too, because a backup is supposed to create a copy, not just an image that starts with a copy. The bugs were introduced in commits 2c8074c45 (BLK_PERM_RESIZE is shared since this commit) and 00e30f05d (BdrvChild instead of BlockBackend turns I/O errors into assertion failures). Fixes: 2c8074c453ff13a94bd08ec26061917670ec03be Fixes: 00e30f05de1d19586345ec373970ef4c192c6270 Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1778593 Cc: qemu-stable@nongnu.org Signed-off-by: Kevin Wolf --- block/backup-top.c | 12 ++++++++---- block/backup.c | 14 +++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/block/backup-top.c b/block/backup-top.c index 3b50c06e2c..0e515a7705 100644 --- a/block/backup-top.c +++ b/block/backup-top.c @@ -148,8 +148,10 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, * * Share write to target (child_file), to not interfere * with guest writes to its disk which may be in target backing chain. + * Can't resize during a backup block job because we check the size + * only upfront. */ - *nshared = BLK_PERM_ALL; + *nshared = BLK_PERM_ALL & ~BLK_PERM_RESIZE; *nperm = BLK_PERM_WRITE; } else { /* Source child */ @@ -192,11 +194,13 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, { Error *local_err = NULL; BDRVBackupTopState *state; - BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter, - filter_node_name, - BDRV_O_RDWR, errp); + BlockDriverState *top; bool appended = false; + assert(source->total_sectors == target->total_sectors); + + top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name, + BDRV_O_RDWR, errp); if (!top) { return NULL; } diff --git a/block/backup.c b/block/backup.c index c4c3b8cd46..4f13bb20a5 100644 --- a/block/backup.c +++ b/block/backup.c @@ -340,7 +340,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque, JobTxn *txn, Error **errp) { - int64_t len; + int64_t len, target_len; BackupBlockJob *job = NULL; int64_t cluster_size; BdrvRequestFlags write_flags; @@ -405,6 +405,18 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, goto error; } + target_len = bdrv_getlength(target); + if (target_len < 0) { + error_setg_errno(errp, -target_len, "Unable to get length for '%s'", + bdrv_get_device_or_node_name(bs)); + goto error; + } + + if (target_len != len) { + error_setg(errp, "Source and target image have different sizes"); + goto error; + } + cluster_size = backup_calculate_cluster_size(target, errp); if (cluster_size < 0) { goto error; From patchwork Wed Apr 29 11:15:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 283797 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97611C83003 for ; Wed, 29 Apr 2020 11:22:16 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5BA55206B8 for ; Wed, 29 Apr 2020 11:22:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AtCFC0GF" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5BA55206B8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48302 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jTkn9-0008WN-Gk for qemu-devel@archiver.kernel.org; Wed, 29 Apr 2020 07:22:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47040) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jTkin-00059l-7s for qemu-devel@nongnu.org; Wed, 29 Apr 2020 07:19:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.90_1) (envelope-from ) id 1jTkh3-0005s7-Vx for qemu-devel@nongnu.org; Wed, 29 Apr 2020 07:17:45 -0400 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:51134 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1jTkh3-0005rn-Jk for qemu-devel@nongnu.org; Wed, 29 Apr 2020 07:15:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1588158956; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/vUVligddMUA0c2cGyY9NKoJ1Pjf53ccgeC2HcFcMdY=; b=AtCFC0GF2tRjDIgWf2hQxmUd9BniIivZMV8M9cdd4/WWcas2GZub0W4BY9Osw4AQu5RYPN Pd6rU6lq4jxvA4WFx3k4/N6U+j31NSIBX0uX36VsuBsRa+2r84WCfHH7tsAnTKRu8A+xaN Rmz7BCU/12u3M0HqPCKxISdJmLcHtWc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-493-7v7SC7I8N1yE3t4a6g6kTw-1; Wed, 29 Apr 2020 07:15:55 -0400 X-MC-Unique: 7v7SC7I8N1yE3t4a6g6kTw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 09EAC107ACF3; Wed, 29 Apr 2020 11:15:54 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTP id 84AF160BF4; Wed, 29 Apr 2020 11:15:52 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Subject: [PATCH 3/3] iotests: Backup with different source/target size Date: Wed, 29 Apr 2020 13:15:39 +0200 Message-Id: <20200429111539.42103-4-kwolf@redhat.com> In-Reply-To: <20200429111539.42103-1-kwolf@redhat.com> References: <20200429111539.42103-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.120; envelope-from=kwolf@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/04/29 01:18:10 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, qemu-devel@nongnu.org, mreitz@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This tests that the backup jobs catches situations where the target node has a different size than the source node. It must also forbid resize operations when the job is already running. Signed-off-by: Kevin Wolf --- tests/qemu-iotests/055 | 60 ++++++++++++++++++++++++++++++++++++-- tests/qemu-iotests/055.out | 4 +-- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index 82b9f5f47d..243d66a62e 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -48,8 +48,10 @@ class TestSingleDrive(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) - self.vm = iotests.VM().add_drive('blkdebug::' + test_img) - self.vm.add_drive(blockdev_target_img, interface="none") + self.vm = iotests.VM() + self.vm.add_drive('blkdebug::' + test_img, 'node-name=source') + self.vm.add_drive(blockdev_target_img, 'node-name=target', + interface="none") if iotests.qemu_default_machine == 'pc': self.vm.add_drive(None, 'media=cdrom', 'ide') self.vm.launch() @@ -112,6 +114,60 @@ class TestSingleDrive(iotests.QMPTestCase): def test_pause_blockdev_backup(self): self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) + def test_source_resize_blockdev_backup(self): + self.assert_no_active_block_jobs() + + def pre_finalize(): + result = self.vm.qmp('block_resize', device='drive0', size=65536) + self.assert_qmp(result, 'error/class', 'GenericError') + + result = self.vm.qmp('block_resize', node_name='source', size=65536) + self.assert_qmp(result, 'error/class', 'GenericError') + + result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', + target='drive1', sync='full', auto_finalize=False, + auto_dismiss=False) + self.assert_qmp(result, 'return', {}) + + self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize, + use_log=False) + + def test_target_resize_blockdev_backup(self): + self.assert_no_active_block_jobs() + + def pre_finalize(): + result = self.vm.qmp('block_resize', device='drive1', size=65536) + self.assert_qmp(result, 'error/class', 'GenericError') + + result = self.vm.qmp('block_resize', node_name='target', size=65536) + self.assert_qmp(result, 'error/class', 'GenericError') + + result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', + target='drive1', sync='full', auto_finalize=False, + auto_dismiss=False) + self.assert_qmp(result, 'return', {}) + + self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize, + use_log=False) + + def test_small_target(self): + short_len = image_len // 2 + result = self.vm.qmp('block_resize', device='drive1', size=short_len) + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', + target='drive1', sync='full') + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_large_target(self): + short_len = image_len * 2 + result = self.vm.qmp('block_resize', device='drive1', size=short_len) + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', + target='drive1', sync='full') + self.assert_qmp(result, 'error/class', 'GenericError') + def test_medium_not_found(self): if iotests.qemu_default_machine != 'pc': return diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out index 5ce2f9a2ed..88bf7fa73a 100644 --- a/tests/qemu-iotests/055.out +++ b/tests/qemu-iotests/055.out @@ -1,5 +1,5 @@ -.............................. +.................................. ---------------------------------------------------------------------- -Ran 30 tests +Ran 34 tests OK