From patchwork Tue May 8 14:58:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Nefedov X-Patchwork-Id: 10386315 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 48F686037F for ; Tue, 8 May 2018 15:02:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3789628DD9 for ; Tue, 8 May 2018 15:02:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2BF3228DE4; Tue, 8 May 2018 15:02:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2957828DD9 for ; Tue, 8 May 2018 15:02:41 +0000 (UTC) Received: from localhost ([::1]:51650 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fG48X-0003BS-34 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 08 May 2018 11:02:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47966) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fG44q-0000ME-Bm for qemu-devel@nongnu.org; Tue, 08 May 2018 10:58:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fG44l-0001cs-M9 for qemu-devel@nongnu.org; Tue, 08 May 2018 10:58:52 -0400 Received: from mail-db5eur01on0106.outbound.protection.outlook.com ([104.47.2.106]:58640 helo=EUR01-DB5-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fG44l-0001bO-6B; Tue, 08 May 2018 10:58:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=G4UyHSyGadH517vuqTaEqlZxdu9TU8LiMsS3YNcOKIo=; b=D7raqaEVQDCE2vXI8X9IIuE9MGmzWH0AVgy2jINpyr5UMaJedUQzx7LDsnfg1tH2C5nYnd89rqJqW0XbyCXRQo1Bbo/EFWdZ+TCj9fSnXXJaqK+Gw58/zXVcmj86c0o710L/z1XOQ71YpLm4mXoWhglleMpcB/h1ol1JcVXJ6+0= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=anton.nefedov@virtuozzo.com; Received: from xantnef-ws.sw.ru (195.214.232.6) by AM0PR08MB3347.eurprd08.prod.outlook.com (2603:10a6:208:5f::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.755.16; Tue, 8 May 2018 14:58:43 +0000 From: Anton Nefedov To: qemu-devel@nongnu.org Date: Tue, 8 May 2018 17:58:15 +0300 Message-Id: <1525791496-125188-9-git-send-email-anton.nefedov@virtuozzo.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1525791496-125188-1-git-send-email-anton.nefedov@virtuozzo.com> References: <1525791496-125188-1-git-send-email-anton.nefedov@virtuozzo.com> MIME-Version: 1.0 X-Originating-IP: [195.214.232.6] X-ClientProxiedBy: DB6PR07CA0020.eurprd07.prod.outlook.com (2603:10a6:6:2d::30) To AM0PR08MB3347.eurprd08.prod.outlook.com (2603:10a6:208:5f::20) X-MS-PublicTrafficType: Email X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(4534165)(7168020)(4627221)(201703031133081)(201702281549075)(5600026)(2017052603328)(7153060)(7193020); SRVR:AM0PR08MB3347; X-Microsoft-Exchange-Diagnostics: 1; AM0PR08MB3347; 3:FqScvbNHBDC5tifDUE/ThKNxZmH0voBg2Q2jF9qg5J6I9iZvHiHIvJRMDP2j+x3CP0QKcaTcUiHTgAINd5+SJABX2vmVXucCC81HvhXIE7SV+rcepWpQj361B/hxHXORWZLCM+tBJErqOfwBhqR/xlJ6jjSIHTAFnJS3gd09XCs+wwbnaMfgxWXFn6ZR2R/uxbURXXvzv7VtXL4B3XozuIQbO6csPFlYfVrbpmrDg5IaSF7yO+tOOy7+4Q2g+eLN; 25:/mHcuEoaoMW1SMY3it8gYNEhK2Nki1zzqpB23WYMbD0lh0Ec2+Iq3cQPLKtPGIslIZfSy3sy3iO0aNoicxqZRkCmVe2CB+W1KItAOc+6B25XiuetOVmHqQWid1EQhpuvBhX77LeuLRr6nAvjARPg0L04cEvSatbKfzcJJneShX06beP8HWcxvPSihFhWuwZtke7dgwj5x1nQjczyZe89dQXtano2VBEUSYHCctJ3xGY1QvIMRye7BP3YcS5eVxOIXeVLV5YJd+GPw6WApQhpPfwS95UM/YQG/0u8uxtZY0oFT9auFhAH8/mgk0+cDpmoK1d9WX+HQD0RIn/DLyEd+g==; 31:auLWFTbpFJgcotMJjpz7pca1drzyp9hRj5yqSBHm8dLscYV8nQs9GM8YJoZHNpN89HBnUCLsG9rz9jvEzyB3BmmN/h2MyLgylQQLNaQs1WiOpidQrnmDc6hzxJcJIoS3mPFXTHNO4wAuhlQh9B/3NR6SxrzwZLW+/tmZbV1nrE28zLg/t3FKO8vJrcWVpDmanDALHPt1XgIzZ0bQH9o93hjWjMyAeQt4tsHgYm/R3ms= X-MS-TrafficTypeDiagnostic: AM0PR08MB3347: X-Microsoft-Exchange-Diagnostics: 1; AM0PR08MB3347; 20:YTRHQK/3OmUByDXZrGGGrB63dSvh2aZ+H1jsWqESpGAMbegKRjky9xEsK3q8IXYT+iPpfKmI2qz0SJlSS5wEQiq1ZvfaXEvhkjBS43O7gRFKMYpMgsI06B1n9xghXyA67ymV/RAUumkphb0+7KWMwo7ALEzthZqQY2m9eTnUMzrSWqo71ocePxSMVLtjRXRNj8yZTveV+Cm+wYnLHGC8Ih55H9U1dJbGIXTdx0Xs/N3IdFuNpN8XuJ72Z7exDIVVh4my/eDrVWqs8HJ989nYyO4477CJtv65se0qgF7eGoI73ZQzFjaXasL2QQHgOO5lULTBQVIgYY2aWnJa9SeUEImMXKZcSRJNJKTUETDNU2jPW5OwquJLQm9dnxunfpvtRhztCEcZBHzqUXLFxXFAkgFEDklD8rhciEfL6vDXKuf63qJVVt2rZbexKCeHYM8zo0/sXruJhGhPk1aHLxdlu7Fd1j1zYygANIAmPH07nOeqFoL8sVwh37OD/Bzqng1h; 4:OSWKbI9jTaenBm9T559RVLfsMY30NivTLqofJSET43ggMLmDeoM90O5UJZpGRlhRvZPN+7a7Pv8Nk9dqgWD4Sz9I567tRq9PY0zB9oKSgIklFdOQqzIu30gcQsComdLaIZrXU6I2P/EAVd9+Wz69RgjcCuukuNSxAwc9XEI16+P6os+OqNA3svuHwd/WdcPDiyFz586j9pEixTKsKDeQ967DtrRLCDiQY8V5EWQdhdq6G+mN0ylA5snXvCtEMXLQjTgTdOJU3oFxE5ocWtyRrQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040522)(2401047)(5005006)(8121501046)(10201501046)(93006095)(93001095)(3231254)(944501410)(52105095)(3002001)(149027)(150027)(6041310)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123564045)(20161123558120)(6072148)(201708071742011); SRVR:AM0PR08MB3347; BCL:0; PCL:0; RULEID:; SRVR:AM0PR08MB3347; X-Forefront-PRVS: 0666E15D35 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(39850400004)(366004)(376002)(396003)(346002)(39380400002)(199004)(189003)(5660300001)(6486002)(81156014)(8676002)(81166006)(97736004)(2361001)(6116002)(3846002)(2351001)(446003)(2616005)(44832011)(16586007)(956004)(486006)(316002)(305945005)(476003)(86362001)(11346002)(25786009)(68736007)(6916009)(6666003)(36756003)(69596002)(51416003)(66066001)(47776003)(386003)(6506007)(52116002)(8936002)(26005)(53416004)(55236004)(76176011)(105586002)(186003)(106356001)(16526019)(107886003)(53936002)(4326008)(7736002)(50226002)(50466002)(59450400001)(48376002)(478600001)(6512007)(2906002)(21314002); DIR:OUT; SFP:1102; SCL:1; SRVR:AM0PR08MB3347; H:xantnef-ws.sw.ru; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: virtuozzo.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; AM0PR08MB3347; 23:CZ/9G7J8AFRmZTQtPRHRNGYGFpiRJKLVcv6ekD7Bm?= =?us-ascii?Q?doT1c4dEqhhVY7SqpJUUgkSlxGPWmxDpUH46Da94Ew9F5/sdpv/m9b2IrpAJ?= =?us-ascii?Q?ubo0k8sPk8ZRr9AKrc87Wcqvbn5e9R36BLrkhC6eWkexCKJIRhpX70g+mPZm?= =?us-ascii?Q?V0rLDwzENfvLWiJS80r+xQgOJ8siAjLSRUj/jGyHcPbzzbfjYD1SsSmrtjh3?= =?us-ascii?Q?A6wfw3uWWobIme9x125vc/WZ8pV9tGxUrfBWRbYeBbBQ7qRnR6nzLz4L1Yv1?= =?us-ascii?Q?y1RiOmjfXdCAatiIXur6XRslmseED/aQi4+8vl2Lq00C7MeZs7iIgMMdoZGE?= =?us-ascii?Q?ioMMROU4uF7TQFWchDL1w6L6zll8bK5Xof0qq+nAmTzZAmk36kHfuPCyr6i7?= =?us-ascii?Q?hF5CXau32yeh5oC99SwcTC+rqCbaYsOcast8j2h8tzhUhXvgoiAopXq2v7Jm?= =?us-ascii?Q?5wlNWMPsrRKmyuN5u1/X4dEiXMQOXMN/T9P0D0oVA704dIKr+OC0h9DUQ1bK?= =?us-ascii?Q?xqDLr/B1R2eQEeHSsYSdNZrKBPCkt21fSeWjqqD4TgjfalDjS+ePCYr/rZFN?= =?us-ascii?Q?uyHfGnrhOwaGDopPJxDVWfGlyD+USOMbBTQ4vDAZ9q0eH3f3MeU3zbsVcCdl?= =?us-ascii?Q?BxRp+0XQhWDtvmldiKdjxgU6wDiW0o555KodgpouBaQfD28FN6hyx/JO0tsC?= =?us-ascii?Q?3plfqRCFPSpzNM30sw8Jxzt4G7s0GzFuVweMNUCDK3n3Tf3MfMWen781cCcG?= =?us-ascii?Q?os/rD8M4KJaHfPPCF40EKKhXkxW4j2rA4qQi1MICdx89JNtPyRvaiDDmuMsj?= =?us-ascii?Q?lZt4dYZFbWlV+BNvq1P1IdeMqKuHwMn87/X6VbxfW22hvSPdELUcYSsr6dQq?= =?us-ascii?Q?r3u0ofsHv8wTDIWW8Ci6fpaXx5LFQR56VCG38DS6o5oeH1ahbxUZ/yoTpZxw?= =?us-ascii?Q?P3Kd3NRn9TgtrGqfXHHzaVK5noVsfSn2DjAVpi7nqSu0zeNnpO+7guBIda8w?= =?us-ascii?Q?FB6i7+BNsXg8R2Toap3JDEAZQFvwO94Rmih5P0ZTJQbmdFyfl0IazNC/GtqN?= =?us-ascii?Q?Nfqp2L/mvP60S58WOiJ3NheQzVJnL18zlEMNjWZjHPsdncYzf3EV63cI2ADl?= =?us-ascii?Q?0g3Jas3GoYWukrpSLFEsXUQPnhj/zVUUx4rK1lE5A6f75B/QN0CVA1h6x1Ac?= =?us-ascii?Q?0HdLezvJrBDR9xEV4akmbjD/yCoBpP+RW+kFmzyR012XYs++wzNvcXmuhTte?= =?us-ascii?Q?F+SMjoX2afahOms/IrCBTdYqBRzcE0BdQANqxQm8v+5tOC7oEc8VPwiFGPd8?= =?us-ascii?Q?YcrKhgXcfRuVPn8TFNOA5nO/ZiTpFKu/AeHs0hsGfvr09IO+4lqmz/6zti+j?= =?us-ascii?Q?hOSQUGSM3RzXw7Cak6UWwdzpUU=3D?= X-Microsoft-Antispam-Message-Info: 0UyRHuepqaOgVtc6KwdCclMg4u24/w4Pu8FxNR5tXK1Xs/1R7ib1KU3JqTcB0W3LAA7HONiUuNitTb2smhT7xBRgEoMUSNPTPvx1VntfI3y90Hh+AoDBeZONs37uBErMxszEImOqqRUUfwZZTJl5nL4R87EARMsjjUfEEQzRqhlGyKF5YzwgM9LQj6INZhbA X-Microsoft-Exchange-Diagnostics: 1; AM0PR08MB3347; 6:sLv4ilTTEO/MSN7DGdMTVfm3DxVb/2QkkIAmV51TTgQrDJfV0KZTYGfJYkdHigl1pYqkDxkx+Clw6QNPty91XgXKA72h8pst6ZzrPXN80tSmGupcrQsH9DCuIYiGP+nRjCYJ2T/wEnJLVu9s77ZgmZK6DAR2yocVzdYtwCAZ7HvTdk82OLJ5+2nXNhK6pGTD0FZydBx9wFoHevreQQKjsI1JGUCE6NmUXuNNGY1c2pTnmO039GMLqpwM9vTJehCgo93YhZj0syjKGEE0Fd+1qUP5wjnLRvgV86d9ozuKZaSOwxq0d8t5ZJl/+ptZCRuA8kV3VyejQkQRxLw9j5LipAyAjm56FDyXgQSLbew/lYiIWBy2B7A51/pXHFBfGlhAoCNoEoBvL0BJhj61Gs0fJnjH6fdaCECSNRVFKgiLAtPmZ4YxyQWckKmjdiIgO+2h7NySm0n//cO93LFnXyyqtQ==; 5:qm5Jlg7BrfqJx8SnzifQn2Bmb15A6fbzlsoPF97HSCgSqA+i24t3cUAcSFkosidQcFhDHsXkBNUVaqvqSc399Pq5+A3QEv7cO37mqHeOg32uMrbGBbjys5K7Mfmi4TQEx0usGIl/ZHgyUB8CflFTRVDAEx/jh1wsZzFZpm4XBkg=; 24:/cs69lO2vyGah8XWeb4Y6FPLQfOZjEiOETtdqXHNfhCgX9x/z1srruqRVZ/Z5XaRHmSo+we63Fdw1WY5jC/NIsAwG40tfm0MRdBjGyyTyi0= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; AM0PR08MB3347; 7:6p8E9+5JFLQx2jhVaS25mjCkVhMY6N+PQ3b46R81daeTHvzq2W2YBGDaSICkAoR5Szh8sw8t2pEB/aukPk86ycup5uovt7BQboCDxSAIHbzO49fCZWyWkawK6HmNpep6U+EN/tCTVBTDwE2OylVlO3tljRAQU61rLHXS1WsWRen81mgbIUAe/BnWFXcPWLBNNuiR3eXQpCNfp7OL9+SAFyJUP0yHKUrFiphmZXqwYhNxU23cnbymMzWI3SCSdyTD; 20:3bhSJyod/Cw3ZFRetUKJ6oZDMfXNuHdNIbSNIg7ogjpKhdlvhFSbPlxxbURKb9yyOTTp0vkIG/toUT4XdOP7qEZbhLhEGFh08d+ce35iEoeZ6DlsUSom14Sm930nGodBRNVPPiu52558xmWBSmgQqPh3uu6tdbKSzC0LU03V8c4= X-MS-Office365-Filtering-Correlation-Id: 4af42a2b-2546-417a-430b-08d5b4f431d4 X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 May 2018 14:58:43.6151 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4af42a2b-2546-417a-430b-08d5b4f431d4 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR08MB3347 X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 104.47.2.106 Subject: [Qemu-devel] [PATCH v9 8/9] qcow2: skip writing zero buffers to empty COW areas X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, Anton Nefedov , berto@igalia.com, den@virtuozzo.com, qemu-block@nongnu.org, mreitz@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP If COW areas of the newly allocated clusters are zeroes on the backing image, efficient bdrv_write_zeroes(flags=BDRV_REQ_ALLOCATE) can be used on the whole cluster instead of writing explicit zero buffers later in perform_cow(). iotest 060: write to the discarded cluster does not trigger COW anymore. Use a backing image instead. Signed-off-by: Anton Nefedov Reviewed-by: Alberto Garcia --- qapi/block-core.json | 4 ++- block/qcow2.h | 6 ++++ block/qcow2-cluster.c | 2 +- block/qcow2.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-- block/trace-events | 1 + tests/qemu-iotests/060 | 26 +++++++++------ tests/qemu-iotests/060.out | 5 ++- 7 files changed, 109 insertions(+), 15 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index c50517b..816c44b 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2900,6 +2900,8 @@ # # @cor_write: a write due to copy-on-read (since 2.11) # +# @cluster_alloc_space: an allocation of file space for a cluster (since 2.13) +# # Since: 2.9 ## { 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG', @@ -2918,7 +2920,7 @@ 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev', 'pwritev_zero', 'pwritev_done', 'empty_image_prepare', 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters', - 'cor_write'] } + 'cor_write', 'cluster_alloc_space'] } ## # @BlkdebugInjectErrorOptions: diff --git a/block/qcow2.h b/block/qcow2.h index adf5c39..2633853 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -380,6 +380,12 @@ typedef struct QCowL2Meta Qcow2COWRegion cow_end; /** + * Indicates that COW regions are already handled and do not require + * any more processing. + */ + bool skip_cow; + + /** * The I/O vector with the data from the actual guest write request. * If non-NULL, this is meant to be merged together with the data * from @cow_start and @cow_end into one single write operation. diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 1aee726..d364d29 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -806,7 +806,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m) assert(start->offset + start->nb_bytes <= end->offset); assert(!m->data_qiov || m->data_qiov->size == data_bytes); - if (start->nb_bytes == 0 && end->nb_bytes == 0) { + if ((start->nb_bytes == 0 && end->nb_bytes == 0) || m->skip_cow) { return 0; } diff --git a/block/qcow2.c b/block/qcow2.c index 2f36e63..019b54b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1916,6 +1916,11 @@ static bool merge_cow(uint64_t offset, unsigned bytes, continue; } + /* If COW regions are handled already, skip this too */ + if (m->skip_cow) { + continue; + } + /* The data (middle) region must be immediately after the * start region */ if (l2meta_cow_start(m) + m->cow_start.nb_bytes != offset) { @@ -1941,6 +1946,68 @@ static bool merge_cow(uint64_t offset, unsigned bytes, return false; } +static bool is_unallocated(BlockDriverState *bs, int64_t offset, int64_t bytes) +{ + int64_t nr; + return !bytes || + (!bdrv_is_allocated_above(bs, NULL, offset, bytes, &nr) && nr == bytes); +} + +static bool is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) +{ + /* This check is designed for optimization shortcut so it must be + * efficient. + * Instead of is_zero(), use is_unallocated() as it is faster (but not + * as accurate and can result in false negatives). */ + return is_unallocated(bs, m->offset + m->cow_start.offset, + m->cow_start.nb_bytes) && + is_unallocated(bs, m->offset + m->cow_end.offset, + m->cow_end.nb_bytes); +} + +static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) +{ + BDRVQcow2State *s = bs->opaque; + QCowL2Meta *m; + + if (!(bs->file->bs->supported_zero_flags & BDRV_REQ_ALLOCATE)) { + return 0; + } + + if (bs->encrypted) { + return 0; + } + + for (m = l2meta; m != NULL; m = m->next) { + int ret; + + if (!m->cow_start.nb_bytes && !m->cow_end.nb_bytes) { + continue; + } + + if (!is_zero_cow(bs, m)) { + continue; + } + + BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE); + /* instead of writing zero COW buffers, + efficiently zero out the whole clusters */ + ret = bdrv_co_pwrite_zeroes(bs->file, m->alloc_offset, + m->nb_clusters * s->cluster_size, + BDRV_REQ_ALLOCATE); + if (ret < 0) { + if (ret != -ENOTSUP && ret != -EAGAIN) { + return ret; + } + continue; + } + + trace_qcow2_skip_cow(qemu_coroutine_self(), m->offset, m->nb_clusters); + m->skip_cow = true; + } + return 0; +} + static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) @@ -2023,24 +2090,33 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, goto fail; } + qemu_co_mutex_unlock(&s->lock); + + ret = handle_alloc_space(bs, l2meta); + if (ret < 0) { + qemu_co_mutex_lock(&s->lock); + goto fail; + } + /* If we need to do COW, check if it's possible to merge the * writing of the guest data together with that of the COW regions. * If it's not possible (or not necessary) then write the * guest data now. */ if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) { - qemu_co_mutex_unlock(&s->lock); BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); trace_qcow2_writev_data(qemu_coroutine_self(), cluster_offset + offset_in_cluster); ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster, cur_bytes, &hd_qiov, 0); - qemu_co_mutex_lock(&s->lock); if (ret < 0) { + qemu_co_mutex_lock(&s->lock); goto fail; } } + qemu_co_mutex_lock(&s->lock); + while (l2meta != NULL) { QCowL2Meta *next; diff --git a/block/trace-events b/block/trace-events index f8c50b4..f85a980 100644 --- a/block/trace-events +++ b/block/trace-events @@ -70,6 +70,7 @@ qcow2_writev_done_part(void *co, int cur_bytes) "co %p cur_bytes %d" qcow2_writev_data(void *co, uint64_t offset) "co %p offset 0x%" PRIx64 qcow2_pwrite_zeroes_start_req(void *co, int64_t offset, int count) "co %p offset 0x%" PRIx64 " count %d" qcow2_pwrite_zeroes(void *co, int64_t offset, int count) "co %p offset 0x%" PRIx64 " count %d" +qcow2_skip_cow(void *co, uint64_t offset, int nb_clusters) "co %p offset 0x%" PRIx64 " nb_clusters %d" # block/qcow2-cluster.c qcow2_alloc_clusters_offset(void *co, uint64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d" diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 6c7407f..e6ed8b2 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -143,27 +143,33 @@ $QEMU_IO -c "$OPEN_RO" -c "read -P 1 0 512" | _filter_qemu_io echo echo "=== Testing overlap while COW is in flight ===" echo +BACKING_IMG=$TEST_IMG.base +TEST_IMG=$BACKING_IMG _make_test_img 1G + +$QEMU_IO -c 'write 64k 64k' "$BACKING_IMG" | _filter_qemu_io + # compat=0.10 is required in order to make the following discard actually -# unallocate the sector rather than make it a zero sector - we want COW, after -# all. -IMGOPTS='compat=0.10' _make_test_img 1G +# unallocate the sector rather than make it a zero sector as we would like +# to reuse it for another guest offset +IMGOPTS='compat=0.10' _make_test_img -b "$BACKING_IMG" 1G # Write two clusters, the second one enforces creation of an L2 table after # the first data cluster. $QEMU_IO -c 'write 0k 64k' -c 'write 512M 64k' "$TEST_IMG" | _filter_qemu_io -# Discard the first cluster. This cluster will soon enough be reallocated and -# used for COW. +# Discard the first cluster. This cluster will soon enough be reallocated $QEMU_IO -c 'discard 0k 64k' "$TEST_IMG" | _filter_qemu_io # Now, corrupt the image by marking the second L2 table cluster as free. poke_file "$TEST_IMG" '131084' "\x00\x00" # 0x2000c -# Start a write operation requiring COW on the image stopping it right before -# doing the read; then, trigger the corruption prevention by writing anything to -# any unallocated cluster, leading to an attempt to overwrite the second L2 +# Start a write operation requiring COW on the image; +# this write will reuse the host offset released by a previous discard. +# Stop it right before doing the read. +# Then, trigger the corruption prevention by writing anything to +# another unallocated cluster, leading to an attempt to overwrite the second L2 # table. Finally, resume the COW write and see it fail (but not crash). echo "open -o file.driver=blkdebug $TEST_IMG break cow_read 0 -aio_write 0k 1k +aio_write 64k 1k wait_break 0 -write 64k 64k +write 128k 64k resume 0" | $QEMU_IO | _filter_qemu_io echo diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index 25d5c39..00a6702 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -97,7 +97,10 @@ read 512/512 bytes at offset 0 === Testing overlap while COW is in flight === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1073741824 +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 536870912