From patchwork Mon Mar 12 10:16:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Nefedov X-Patchwork-Id: 10275921 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 50E2260467 for ; Mon, 12 Mar 2018 10:26:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A60728A69 for ; Mon, 12 Mar 2018 10:26:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3CD7E28CA4; Mon, 12 Mar 2018 10:26:44 +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=-6.8 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED, 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 347AD28A69 for ; Mon, 12 Mar 2018 10:26:43 +0000 (UTC) Received: from localhost ([::1]:57561 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evKfC-0002VH-Dx for patchwork-qemu-devel@patchwork.kernel.org; Mon, 12 Mar 2018 06:26:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33688) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evKWO-0002pW-4t for qemu-devel@nongnu.org; Mon, 12 Mar 2018 06:17:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evKWJ-0006tB-Aa for qemu-devel@nongnu.org; Mon, 12 Mar 2018 06:17:36 -0400 Received: from mail-eopbgr10092.outbound.protection.outlook.com ([40.107.1.92]:46366 helo=EUR02-HE1-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 1evKWI-0006pb-Q8; Mon, 12 Mar 2018 06:17:31 -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=kYl5FZGv2Wc/8+k5A2jwKWiKem7kPmg4TNLlKwcw+5g=; b=S8iCaxxlNM9tAXXFbKkwCWr/EmS5P/f6szXJir6j5nsk3+JWU/ZChi89j8qpRXVnBTD+0Ta5cUOzGK+DShzKQ2h5KhevxNHt3CVAU3T36HMpCzfQXtrH6v07Rh+dO5u9X/mFN9UKrvXJWRCrrNuTkht+tNVnH3R9JyHMFodhg8A= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=anton.nefedov@virtuozzo.com; Received: from xantnef-ws.sw.ru (195.214.232.6) by DB6PR0801MB1991.eurprd08.prod.outlook.com (2603:10a6:4:76::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.567.14; Mon, 12 Mar 2018 10:17:27 +0000 From: Anton Nefedov To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:16:57 +0300 Message-Id: <1520849818-6915-9-git-send-email-anton.nefedov@virtuozzo.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520849818-6915-1-git-send-email-anton.nefedov@virtuozzo.com> References: <1520849818-6915-1-git-send-email-anton.nefedov@virtuozzo.com> MIME-Version: 1.0 X-Originating-IP: [195.214.232.6] X-ClientProxiedBy: HE1PR06CA0148.eurprd06.prod.outlook.com (2603:10a6:7:16::35) To DB6PR0801MB1991.eurprd08.prod.outlook.com (2603:10a6:4:76::8) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: fa0e9c9e-485e-46c0-d494-08d58802758f X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(4604075)(4534165)(7168020)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060)(7193020); SRVR:DB6PR0801MB1991; X-Microsoft-Exchange-Diagnostics: 1; DB6PR0801MB1991; 3:mFB2kwpn9Mm+5d11bY+X2TbNLQAug2o1ZXtmoXNmSCI1YkPiL2yHdM/iSNdo9Jydg15s4sVMFqwjWmR0Iwt9tbim0IrOLUbEY6frq8r0K5UhDbrV6v7hCAX5cajmmjkcBf8mDcOR8iSsEFoLPbzno2ydemzZWcDnql2UsgvBJKIp+cszKXu4xHwmjX8n4Y07i4fLE/MD/+8nxFPH8staY076mUGfnJUXy501NjnRxPryl5OKP+ko0DH9WXGRblrn; 25:vQToHnZ084f4t2nlUy1jeU1N1P1onKqsrk9tKuzPMPUfbDQkjdZtIhrS+ElRt6aEnYFsEkymGXcDmj4ZH17Wo68nASIlwMagBlgjDqIJuJIDqgkIT7OaMMtszeLKLZfgUDBNVm2/VP0UYiaX2bhMwbx8amqC9dMI+6XW6dBM3jzBcyJSl4b/9DJoM9NLSkTMvJJsPi76gXhFYNt9PhUongi/u67xdPxFP6cx7naHBtjVF6oUvV0eq9S01jJIV/GIGGP4EdO6RYJzS+TaOYhK/f7P1iU6x7nu0QNun2DGngvWrzqP8j6V0JVzxad1yynn4xLMZQ8qAFdlRrnLY+1qpw==; 31:Hj+oXC/9ABzXKNKg0L8c5CADW0xgnCWZhoaW0blAexb5V9biLWWGwnMFlMc+8iVjyf/ssYCyZ8skVbFvORFir6DeynPJO6j6i+uluImch7dnk1mtiMK0ynprJsM149qfrx2iv8A/3ybruercZjaAZtsCwsPlye5rGG8QrLYH3fX8PUggTae+/E+LBSUNngfwNKm8jWGrpnpXjg85y9RyZR5ujWoQJ94C0v8htCSAh2c= X-MS-TrafficTypeDiagnostic: DB6PR0801MB1991: X-Microsoft-Exchange-Diagnostics: 1; DB6PR0801MB1991; 20:4bD5AC2lZonW5RNSyhMsB0a6mHoBpIsro6sbbPzHYJzru8ImslqTmfm6qTidXD+j4bacRpgzjNnRVY0FNl3lszZi+9q40I7lr99kQu4KxlQUIb6H1u694Q4+jBnTURmYCFQPgJdwtU1rkYkWPrNQMsb6n3QnMvgk1N/Dq4jiWXyijks6dXpkZo1HGQx76idIIcC7KYf0/+H7SouxZQV6joPVNp9B6m8umi5lAQw/hOAYhjD/MpiVpUaxXztnqEVlML2Ugdi5b5e6W4yzqjadQYO1gwsLQujMK1jsVj/2EmC0MyD+ySYttsuwHsW0eindf4BmqPNM+7e8lK4JbMGToZRHAv3RjS1ehMxdy3JczVECVcmstrY3khaDFmSAW4xf+9SpYRzr6jtOPjgNgdAnre9wLzplFIQexjpqVup+3SKKFA2CFj4NfR8wRJc3uBJgFhYbXnnN0aSc84ibpgPQaRHVyg/QzbjsjS91nw8O1+Isxqn+q1H0ahe5rRLOb9+2; 4:5MlNnTtdpoiVfne7Z1pfqxH3THZdvpF90GFCs6KwR+Y97MkZiQmXwAbfOCIn0Tx2u/WP/w/S7/PS7VUepikLFWbasC8DJsbF3mjtV5qT0NbsxuWyKcDKWAHtJU7ygEw8LbVmjgJ13X/8TdQERr2jfHoUT1ONPLaN0bw5l4TyRE8dt+I0Q75Q/wfmb7lQHortaOcasuGSsnMEVT4JK7lTCe1JGF5Pj8QGXE1/QxO6f2yvJBDKoBpU+et5Dar6tdigjQPcWUosFXM0VuvM4d2Tsg== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040522)(2401047)(8121501046)(5005006)(3002001)(93006095)(93001095)(10201501046)(3231220)(944501244)(52105095)(6041310)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123560045)(20161123558120)(6072148)(201708071742011); SRVR:DB6PR0801MB1991; BCL:0; PCL:0; RULEID:; SRVR:DB6PR0801MB1991; X-Forefront-PRVS: 06098A2863 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(39840400004)(366004)(346002)(39380400002)(376002)(396003)(199004)(189003)(47776003)(106356001)(4326008)(81166006)(16586007)(107886003)(8676002)(69596002)(6116002)(68736007)(3846002)(105586002)(50226002)(386003)(6506007)(81156014)(8936002)(55236004)(2906002)(36756003)(478600001)(2351001)(2361001)(25786009)(316002)(59450400001)(6486002)(53416004)(76176011)(97736004)(52116002)(51416003)(66066001)(48376002)(50466002)(6916009)(6666003)(6512007)(2950100002)(5660300001)(26005)(575784001)(86362001)(53936002)(16526019)(7736002)(186003)(305945005)(21314002); DIR:OUT; SFP:1102; SCL:1; SRVR:DB6PR0801MB1991; H:xantnef-ws.sw.ru; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: virtuozzo.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DB6PR0801MB1991; 23:cTiKMaQaSmFccjEmQIOwOhS68t+kobyJk9pyG5Z?= =?us-ascii?Q?VZW0RoS+l/ACqtBkQr1iyzqYepI8+jPXnsEfXVg6glEeeGG8x1QnpGkchAPy?= =?us-ascii?Q?jkREf/1Z2ZJ1JCBna6RRXdVWzbChJaCahMXf9bbFAlWjukX/DHgCwU9g/GoB?= =?us-ascii?Q?iOl3i4ST8qPNgIETUdG93Ut30rg/bPttNObiri9Y1I2maHp9qlADKMc7sbfP?= =?us-ascii?Q?dhSBKTFB82FZNngPQQn0SQa1S0YEmz1g2NY1Qpijl9eJIErhF9mR70MvXWGK?= =?us-ascii?Q?fQxv9PlySz3EjowuMHnk/NFoEpIRKlA6ntvoyqvEmBwpPII6FgbOME8xAMD2?= =?us-ascii?Q?8kJD2RArh0v0/APVo1/9kC6wehdprFXlym1OAyu9tGLa7WLsCPlu4D/E4ekm?= =?us-ascii?Q?1oUNLomCbGFifQKWPlmnNm65TACYcJgTn5aOgzAsGocLFDsIC+YoBA5MCm5O?= =?us-ascii?Q?vxENH9uwOuNexknjwa3GYy5ORYvgZScf2Xm8mgwDQlDVjIDnzRyjhFEL9XQn?= =?us-ascii?Q?iSqcJG76K/Q2BzABKASCCLG1DncI37shxIwZAms46sDVXsWFAVJtSB7VuWag?= =?us-ascii?Q?F0GSTr0LF+T7NJhOxtu98XhowFaTiLL3MDAhDy5DvZFjFhPqAzpxqjnJlToQ?= =?us-ascii?Q?Q3OrcmxOklDuGYMWUKq5sVNrPTqBw4Sd61lZPE2zUJrUcLkRapJas1DqQEci?= =?us-ascii?Q?grBsRc7zSkhSxl+mtMRN7doZtZDBjiT3jIvFt1Q7lfOlWu/RBl5YV2rMh/4V?= =?us-ascii?Q?kR3SMBU3eZ0geC/2hSqdZRTEUXrj81cy64aswk5TdDYQ2NH+TwJKOKcaq2CK?= =?us-ascii?Q?dxRni6W3HK0oHeno14q0PwcOSfmaxwy1twfm6Ng9Zqc4dtyWjPcM3GtfzXEt?= =?us-ascii?Q?vHZGlDmdo/Xr6l4WxPZlmCeoI+1AY6YIL+4Drw8Vs+ghdyoNoQ4/GELXrcee?= =?us-ascii?Q?zEOYHOWrqE1Y2oABR8iN3sDrDiqDuC1m4DhLn4xMNOcbZpfQeIqvYEV0EMBA?= =?us-ascii?Q?hMjMm3gblCeRM0FTD8PS8CR2Uk2pf1qjlyN2zdv67nePdDiOsS790X4oSzAO?= =?us-ascii?Q?mn3u+KHOGoGXvatWOeZqXf2y3bS1Stvh+LFutYd5eheceCmfbqN+ypq+g5Ci?= =?us-ascii?Q?L+zbuunN20r4rhwORVmWvrrFZDnMypaDakySYJBlTmxsC5mHPYOvKM42TjPZ?= =?us-ascii?Q?TcDemDbGuFOK3nfLwRUZBSpx/d2VWS53UaHVwd5pFFAJcO+RW6QLrfAUgTJ0?= =?us-ascii?Q?aScm/QLvEn1XSQzJNtqKnS4Rcss4Kij3uOicrZPOkYy0X4SDfK5LDYrHb4Ju?= =?us-ascii?Q?1UQ=3D=3D?= X-Microsoft-Antispam-Message-Info: WwYjbSM2cP3QLKrMZYMSaggl4CCWpJpV/vSBmArhwuF/8skWjBsE5RNYkn9eaf+FWVUWdzYyVjso28Z7az4OGEr0OiUUJOSKZEsBUw4Tdnt91max54HPk5nLh1bxPKsNukjQrQr1Vyv26Vb5PDwnmRxCkpNGIvOtxfX4Mh1EtpsniAOIhaBU6aw3gnmiAx8U X-Microsoft-Exchange-Diagnostics: 1; DB6PR0801MB1991; 6:bMoU2SLuShd71sx69S6PlaRXXkhDykZYD9A3dNTofumKiytN/pyOtOxBVGFtPLUjbda71koED3GuFnSucxlServhV9dWS0XdI+kZGi4j1li9oDxfOVkV8Cn/cyvYG+5Nd5iXGdWjs3Vc73JZUNH9xpNKgYlb4nB8rsrWaGJeTApPvAdxevfxJmsVjuZVny2/MXMCYx0gkfr6Xoy2+rknat/fRtHFbphSy8PMH00Ss21l95QS2sdoq3AnluUKnNQkyqdW63zW6FDh7N3L0W2l0gLwUwZ2meKH21zPwlP78VP9mvW9emwMmxa61ubBTyRQevPUNmPZ0XNraJiI+RtruYG8nib5AJTwxC8u0VtUEgk=; 5:keU9seCnG4XkMfrgZAMLNqPr6xhaafQAzd3AWf/31WaQTHd8KYA+5yIVq367OeftOthHWyex0T+HXoMa1sKw3mXlg7MhoIRIKPQ2d+iRewPHAtYRiulhtsFJPCPHB8OsqUBZMLCfFNuMK7CImOJkWoQUWE6xyixd1n8WOYh920k=; 24:zedr6xABweeuCxzC84jiWZGKZudHk5FqGIBXQEJXm2FjpLB61WDSCHqn0jUsJi+FZdUHHmsFV/kOxgbzprsRpCnyzAhZLFaLj7fxiTe4z0w=; 7:38qNPS3fqmWgwOPJGx3l01WPQq2L8eP6587We9+ZWe8DwT/H9aCpAQuTraCOXclNh8D1v5Iv73KIBGWrB5aNynYFigGmjEtP8p666HrdjVUqYoAWdrqD5vd4iAKk0na/tTFzN5VdWfRmMYRWmJRcKqpO2LLqEIGmuh9XVmocFrw02tkTwgm+lSXuhkTvEUzjeZb+ThBSJbGJ6tw4SgQacwE7oDmyvw5sB55+CroMYgLZI2T0Aee52a+zpyFiIL2g SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DB6PR0801MB1991; 20:T7lcjiA1/Gxa/kmfJp8gRmqZdILDdR1Fw1ERwpNwLzIjTrwa9sUXR/Qn0e00qyvijQBmhzqp/Qf/BDO0xLBbjihmWqeayMnVpmbpaRQh9WPKiXLDuTuShBi9HSdnveJNJ7REA9Fu4AWdJfPpx0B9cDT16/BIcDyQXjM9aiiGPJw= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Mar 2018 10:17:27.8653 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: fa0e9c9e-485e-46c0-d494-08d58802758f X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1991 X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 40.107.1.92 Subject: [Qemu-devel] [PATCH v8 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 --- qapi/block-core.json | 4 ++- block/qcow2.h | 6 ++++ block/qcow2-cluster.c | 2 +- block/qcow2.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-- block/trace-events | 1 + tests/qemu-iotests/060 | 26 +++++++++------ tests/qemu-iotests/060.out | 5 ++- 7 files changed, 108 insertions(+), 15 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 00475f0..da61a0d 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2584,6 +2584,8 @@ # # @cor_write: a write due to copy-on-read (since 2.11) # +# @cluster_alloc_space: an allocation of a cluster file space (since 2.12) +# # Since: 2.9 ## { 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG', @@ -2602,7 +2604,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 1a84cc7..2cf7dfd 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -379,6 +379,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 98908c4..0624d65 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -805,7 +805,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 071dc4d..2b0ec3c 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1866,6 +1866,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) { @@ -1891,6 +1896,67 @@ 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) +{ + /* content with false negatives, giving is_allocated() is faster than + * a proper zero detection with possible actual image seeks, which is + * performed by is_zero() */ + 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) @@ -1973,24 +2039,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 02dd80f..2045ac9 100644 --- a/block/trace-events +++ b/block/trace-events @@ -61,6 +61,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