From nobody Wed Nov 5 15:59:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zoho.com; dkim=fail spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497356569703298.9532871443379; Tue, 13 Jun 2017 05:22:49 -0700 (PDT) Received: from localhost ([::1]:43018 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dKkqL-0003jc-Af for importer@patchew.org; Tue, 13 Jun 2017 08:22:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60688) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dKkmO-0000zV-93 for qemu-devel@nongnu.org; Tue, 13 Jun 2017 08:18:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dKkmK-0007Cb-8Q for qemu-devel@nongnu.org; Tue, 13 Jun 2017 08:18:40 -0400 Received: from mail-db5eur01on0128.outbound.protection.outlook.com ([104.47.2.128]:54338 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 1dKkm6-00073l-UX; Tue, 13 Jun 2017 08:18:23 -0400 Received: from pavelb-Z68P-DS3.sw.ru (195.214.232.6) by HE1PR0802MB2555.eurprd08.prod.outlook.com (2603:10a6:3:e1::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1157.12; Tue, 13 Jun 2017 12:18:14 +0000 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=XH7mxg1eRQlhEkEq6QRWWZCDv8hbvYgictuipS26TTw=; b=I9VDTZ7DTc5tXN9PzR8sPWaFzUecIxq/ybOmiRvWy3sErCW1ME1Lj0zTy4zd/nEKfWtJAXIzmw9UxDU/SGgyO6jgO/cXYcd5eWeisK0UnpWegwxvuBrW2mzHOE1cR4T7vhpyntPa2lSxFeGH6NuEO4gOYnbAofkH4RIPOoqT1HY= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=pbutsykin@virtuozzo.com; From: Pavel Butsykin To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Tue, 13 Jun 2017 15:16:38 +0300 Message-Id: <20170613121639.17853-4-pbutsykin@virtuozzo.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170613121639.17853-1-pbutsykin@virtuozzo.com> References: <20170613121639.17853-1-pbutsykin@virtuozzo.com> MIME-Version: 1.0 X-Originating-IP: [195.214.232.6] X-ClientProxiedBy: HK2PR02CA0136.apcprd02.prod.outlook.com (2603:1096:202:16::20) To HE1PR0802MB2555.eurprd08.prod.outlook.com (2603:10a6:3:e1::20) X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: HE1PR0802MB2555: X-MS-Office365-Filtering-Correlation-Id: 6dffc150-002a-4996-3236-08d4b2564727 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(201703131423075)(201703031133081); SRVR:HE1PR0802MB2555; X-Microsoft-Exchange-Diagnostics: 1; HE1PR0802MB2555; 3:gcqyhEBUChcO54MMLYliRlzn0FuU9dazpI0sGj04eqeVXoRqkcq4vUSI5Ngr4Otl3Y+rAYPfZ0XNFf1imY0bBYiPVl6rVUvlWUKNcgRcD2Eya8YRBtf7F5GFLfz6vyWzz3+hoqG1cyj13V8N2+bdmO4mMtxYaLZ5lovjwhBORRd4rSwuc9Q/6/rVxH2YOt++WafE+fENf282dUs6oQX/mn0Is0bxs5PAbNlHu+UPTssNI5E8BWqr4mI60/OqGs01psFgQVGZa4sQK05Y5w6iorsSOr5tof6xCeloHMy0of7R+y6wx2Sx+JKLl2UnZpCiTPSEbJnQMddA1Sk06rFtKg==; 25:jeFBFjIiA7IFo7OWb+rjy6f0mqkpHX3PJOgwbJIQRZVtdESLMFWJxfEAoyPMMWUteLFdAu2raxJTEq5oi2JU2savpXqJCpBHtAwTeFVbp9BABQuoFqS2OOdwa6JtMPphXTIH+YZXWw6c0cyNcdVLzHsbxUw3W7adFewTBpLrnK5tJ/0fJArWXYpB24kHf9MDrXRhCEzCFFcBzajKWT48vR9R9n4aCYVJJqHn0n+oVZ15iMgbKXNYzWlAlPCjbTd2AiN7dwWmOhuU+nbTMkfWDOno3taT+M/i0v16+dyKJN6U9jL0qfUKqMioqZhTxZAevCrXd+w43vBFH87tVre750utulGHso6bBQYEG00hq0HUolyTLlAMjIMT64CYfgvkneHMhL/ntPqozABxFOB+lntAoMFNaTT4iZPd3kKaxSsn/7qHdu2yHT1kbmNATm0AlVlXdSNCblul+lwoA72tQ2YliAVDTwbbpbaLavrgURg= X-Microsoft-Exchange-Diagnostics: 1; HE1PR0802MB2555; 31:ZXIDbx9FmHSZfjYANC2EiOyIlV4NDgtkXHxJeaIsSBcNoG9/wNfXzwtMIfP8M+qHU775oecDhoanljjewlLDLxiINOedsEGx83zIM2MnLDq0QCbIccMYYngt9F68P0dZGCywX9iOI+umQYFCuyDHf/kZj4YILx0i0jzodi6Wk9jeIACW4ECEqODPYCV+cUvSwirVARv7ei/03tJs51Wb54NshojDmDR9h4a6Scmx4XA=; 20:L68NEW2d0c9EWrujYkG1m1snvHcup/UI5JoHsUim1MUQtmSerXaeC54Hch4A7YtEwk11g8WVRxQce7C2k6BFUgtoF+qY7wzYIPj0JU2Iv+4vJxA7DYhBE8hrEiK9oy7eywkcoTNRNn5MayworDVSc8tsh87PATmw2fwBsoAg0uR47O+Qfp9pLS5YufxQSep3QQqu2XxQcIzKQ9Oe8iKysPL1iwYw1lmYVBG7qQ0O7LNSFVXBuhHcKaGE8U5zALGkmI7OK5vMYCsztT+FyoGkd3hzrM2QIpPtTzGaeE+k4Fg1wJjcngK+5ZzIXTr0EG12mUn+dMr1ZWISxKEENnM0TE0/RXNhtm9yLhL6ZygDXG2UCpaWK44EbtBYBMafETTMx1nu4vLU8riDT260zU51bMam7ch5+CxN2X2X4Gl/slk= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(8121501046)(5005006)(93006095)(93001095)(3002001)(10201501046)(100000703101)(100105400095)(6041248)(20161123560025)(20161123562025)(20161123564025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(6072148)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:HE1PR0802MB2555; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:HE1PR0802MB2555; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; HE1PR0802MB2555; 4:nXsvU2g1Lg9ImTvLVk374awhVx/AiAYw5BAk4gOA?= =?us-ascii?Q?WVLaa52kjER5yoODKj7j9Yg1p00hqmH0beNwQsmL13Wn9PjHnxUo6MT9Rd+9?= =?us-ascii?Q?fxGAHH60CNpxooFck5IgwK2Gsu+vhohl4cfSCS7mwR91I2Gp3ba4SUbeTbgH?= =?us-ascii?Q?9Hr0c3D8HLviEze4RBa420ocKVon1ezL0/MK9n1LD4oHjMSw5/C6isC61CS1?= =?us-ascii?Q?++nUvyWfkljGT9HbrHwMnRZ9wUhGF93nwyu1Dw+8rALG01NWCLfJH2TRevKw?= =?us-ascii?Q?v3lP7UCEb0Wy9lSPpeUXnVNnIPkv1D1G0gm6xGyYxeNUlwwMPb8t85xyZoMk?= =?us-ascii?Q?wdXovxv9822b+Eh/qwGXO7vjJc9flMJWC49aI5cWOtnwgVI15DrLxfubOAqj?= =?us-ascii?Q?VganxEwoI978jGb2oZoM9vQ9czaDkaskUfLeKzmNCWoSVrrzLsh+9gqfOBqy?= =?us-ascii?Q?xqOA+qfRpbDWgGE59Az5bgyFJCBAs3+ZgOz7TUhAZNCDlI7g+356rB9ZeAvj?= =?us-ascii?Q?Zf/eD+K/j8i+SFyZo4vpVYRF1u5y7pkbF6BS/+oInVxhy7rmSSa8g8yRjuJ3?= =?us-ascii?Q?ZCma+WNsxlqhMs5boDsWYyiA5MuG3wG7y0qhSBu/j+PGinwIFmfcvjQADJpz?= =?us-ascii?Q?MBKNy4qM/ogJ46SO7uaT1vyV/XvyB9SGBt1OSezDOau4YTsAiFn0SPZkzy5I?= =?us-ascii?Q?V2pmUZa5HZnPNeiAN91MogT/ej+KyPnOARHJ/g7QSK0fMCbTKcT7r07wC24w?= =?us-ascii?Q?nj9NDNXQpq4zVXmrBVfI184vOPjbMDN8Ts9FXlAlSAdGzOWp7VtZRsBKvlGn?= =?us-ascii?Q?+HHn/wB+ZgEyUYNi0BB0rjDcHRm6GbBfW1w595Fl/OzKSsFvHfuV7nYPUsPI?= =?us-ascii?Q?a0tOhpjyl/nHNHEnJJjMUVxJHYlBWyEjilr8NzUJLAYHIgydbZ6eapr6NO6i?= =?us-ascii?Q?LLLs4Yyg3nDOrXPO8PKkl/QvPbk+MJ4M8gjyswpFJvM7uAiLgh0Etr93IOef?= =?us-ascii?Q?9q9cWyqv+X+EBeBmiNFUyCpOQgkwsLOxSM7K0gD6XiojYfiBozMw7wZypHGn?= =?us-ascii?Q?Q1iEqAkv8le6Tr3EBaMcdtnCIQwZ0Y2ZMEaVfcbaF8fJv6QvHyQh/F6YpycG?= =?us-ascii?Q?YFxnhQYQ8eN3Ig/yJW85EokGdQKhmOXU?= X-Forefront-PRVS: 0337AFFE9A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(39450400003)(39400400002)(39410400002)(39830400002)(189002)(199003)(6506006)(25786009)(53936002)(50226002)(107886003)(110136004)(4326008)(53416004)(42186005)(6512007)(33646002)(6486002)(106356001)(38730400002)(5660300001)(105586002)(50466002)(5003940100001)(101416001)(305945005)(48376002)(69596002)(81156014)(189998001)(47776003)(66066001)(8676002)(81166006)(6116002)(36756003)(3846002)(97736004)(6666003)(68736007)(86362001)(1076002)(50986999)(76176999)(2950100002)(478600001)(2906002)(7736002); DIR:OUT; SFP:1102; SCL:1; SRVR:HE1PR0802MB2555; H:pavelb-Z68P-DS3.sw.ru; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: None (protection.outlook.com: virtuozzo.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; HE1PR0802MB2555; 23:z973VQqVFawEVHMTLXMXL0YfwgAyKj0FN4XPs9z?= =?us-ascii?Q?FgVobXmvXcq/CDrIVatjijTjyCvvG9DXm8ECbFYGBGIKSMkByrwD+3DJ3nxs?= =?us-ascii?Q?UN4rbu8vfWzeNDnEFaUPCKydCgKLMuF2At9BEj9tE0QuRRA1e9eB7R0pOph3?= =?us-ascii?Q?9A9RmY1uPF/NGuFROACmxgBzJSBDv28lhjdnSm2xRzaeWmOEKIEDHaL96Mdz?= =?us-ascii?Q?JHBBP1nY+XLoB4ISRwgdDZPQaRRVHN5MZkR5f6UOxcjQLd9nb+xJwCBcZycj?= =?us-ascii?Q?LKxnBDBeL7F9oCDLWjjWUUehXn+7XuQmCWRvQhpdeLaYyA8GqFVaIubNUKjF?= =?us-ascii?Q?40g+nL/zyr5LBA28WXYogm8BzxUYXXmeCXsoQUefYomvQXHQMSHK9b8Cdpe/?= =?us-ascii?Q?nhqCoi65C8Wzg/4JZQLcCl/VerGezral52Fl02r0efBmPbdWQvFFXX/VEcpU?= =?us-ascii?Q?x/UBNhYz9azWyrxTuUhqL2ezVWZEM4R4K27FSsDLb7NaG3w/dFIYzSosTPn/?= =?us-ascii?Q?hySjYaUba5Vs4p6WjYpt4oMW/Dv96xweW44c0Eea6VhPZmkkhOxJw5V/nKML?= =?us-ascii?Q?w32OEAkRYwsJDqi+stkU6412C7u2V3QJQDfaoLIhF5jQ11lX09q2OfjHC6yo?= =?us-ascii?Q?6c7tYwLrAeVCJL/TJo9dEblQLDTFSE/t8RpJPo1QGQEEncxZ28jlJUgWusQx?= =?us-ascii?Q?vEkODMCa6v8GkHYyMVmsj8I5hpjJQGqO5qmVNGTT45z4v1+TZNgbsP1KyaKv?= =?us-ascii?Q?EPsqC/k9Z18AJIRrRm9j5vlctZTNU7rh8Zf+UbZkzSLhQXqzu99VXF/SEgQI?= =?us-ascii?Q?rMbJIO5uDlQAu2HekRrKs263PqoHzOApyfpEjreuLijYmslrY4irmIUXD8wu?= =?us-ascii?Q?FNt56C8GjPVi0WTAoL2usz4Nh2rW6nUcHTfpiEeSF+uVuP1VXkuKUTEjOAn6?= =?us-ascii?Q?jtPnk44b+0JZ/pCquywAS6xaV+yFRAAC1fHUDEaCyspibTXY/bSbsqXMjuYd?= =?us-ascii?Q?QQnLhAk4MbuQNjGk2yG8QBKsE7alcvlyazBjlLCYKlIQ4ZML7KdSBdQUeeW1?= =?us-ascii?Q?nx9QOibqA5t/GdxEKBmNOparAUjNpYwov1GZXlBOFc7ugfa/rAjEKkY3zWSV?= =?us-ascii?Q?26bpny2Mn67IZWCJT0S91sA61nBcFPH7g3zL5AS63qkD/+ohYJbIT3BiyvZC?= =?us-ascii?Q?YscBEESn43OXUtcReeRIEYZT9LXNQuAL5x+9bC0a58UzrAbEhmHhJvmNELQ?= =?us-ascii?Q?=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; HE1PR0802MB2555; 6:ZgJQY+BNjqxf+3vxemiQ9UgYo2FqIK0FpgTWmVo8Sgr7FIiWIiH3eQlBYYbFzQZ2IMZKNkm7+YTke4pPJZv+n/+nj5YH/7wVHt1DklEqLjM/2eyyTHtZSniXcwQocdY2DhbejUIsn1e6614zfZuAuqaRZcv3TXrue2gd5iL1ZpM2/2vXy7RhJrfoAcuIucQNKh2eECnX71wZixQuiAZPcMcA7ANSRLkyX0XTJDa5HXgEZBJpL/PclZEUJD65toNfcaSj4uxlsH/A+t9KtM6wOHZ5WZ2M1aLuwxS47RnVDltj06Mae68qvMkbnIY2AOE+rQ0hAB3C3KB9o9Ca4TGe65gUck4R7qzcYct/89qbO3Vttl01TYwgZimQjXhoxYOr6YnjziLqQK7j2cHwUvE/pkWN66cACl+r5cZ2ZDDhssgdC3TeH9tm9p4YHTVvNoijxffRYX0vvOJqaiW8p0ucu4D3qLu2eahHIfKPFeF/YTWnQNvUgXTv0s8pbHSgVYSWKNGRlIIvqOFxzX1pMLx6kQ== X-Microsoft-Exchange-Diagnostics: 1; HE1PR0802MB2555; 5:6lJ2sZg+iXB5mPCc4X9/JTkN4SsPqvO0Cm8UQYyALFpYPCiGSWJ5Gwii9haB2FJv5t32znr5m4o1/Fc1TECXyQjSCOk/XHjOpZ9SUBbalY9cSd7ywLR9iR0cByiryLz5HkxZ++8t9Jv82pL3P3tXpc9KgG5Ae1CGGaEsGAqo6TgcyQXxSjvajmPY9SNgUa4ipJy7qGoqJlKj2KvAjifnLYry4F2TFlKIWLaNq524PEpUKpLsqnuzuPFQEw2GN5Xf1dbi8DG0DAgDpx5cjDTGgZJgUkMDAIEJEAZpKn0XJ7DHSZuvi1z5NogW9DyIWmqYlK81go2s8Rx7380D7Pm4BG/NzlcOXWwqpJFfMhWczXfpfAEktoF4D2+ccJCY+2ghBHfYchRkrh5RDQGNo25X7fYLE/S+zSeisVHVeRPIkyri6aCSJPAj4kvFJ6VzQNfn3yNK0MHSkYoAmzIFBO1AG7CjbPzOAjyUwRBGdQNRh/cp8y2rFyV9fLIZXhVy/GI4; 24:8Od1kTpwakKqwobLBZe5JmBB4wSSCGic4LvQCdjzhfLfjQo8JERzncRV/A7vKWitoWWPSPC6QJYPQMFvEvCCpkcDhUSJJ2NvQIB0TrLYP+M= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; HE1PR0802MB2555; 7:XaFaRMomIaWv1aOw2yvxlbCUK6naVJ3OYJqhIJGGMFOEsa4JCZ0CMn4cOV6SgVVH1bLdMKzIIqdj9wXuUra4DXTBkwWdTGjl240QM9GFz+Y8D7K7hELMufGXMXHmpC6oQST/7UdgjRTPo2zBxo1x2bIBX3ZWmP+/GoyoEAbmBYQ1OedyoGHy/mN+k3JNARjGTdoPFKsvm1U7nvEYLgAyPpSaeNzGW3dubD3zhgFwSkdm/S17xTOVL/Q/gVfXYN+pE00fXKNSCQXu7VPUO8gIewIB7JYVvmNFq28XRLoC+r+do8FaC6ZogQAPaRZjHps5v/E1iCof1vzf653JLK6hoQ==; 20:1thCj0+eaaUdgHQOVVpwzWMwImDoD67PXo9izCeFAeFwfd76IdP3ptoHAV67nD+/va7hB8rmUNzIs3xLsyWUbPyWqwQyx31Mt4LjtSlfGHvuBlwN/VJav87u+FXn7ZgP4yXX3r0f+6w65gJ8sLgkjo1eQ+umo7N0V8zhZbFCYaI= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Jun 2017 12:18:14.4461 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0802MB2555 X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 104.47.2.128 Subject: [Qemu-devel] [PATCH v2 3/4] qcow2: add shrink image support 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, pbutsykin@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch add shrinking of the image file for qcow2. As a result, this all= ows us to reduce the virtual image size and free up space on the disk without copying the image. Image can be fragmented and shrink is done by punching h= oles in the image file. Signed-off-by: Pavel Butsykin --- block/qcow2-cluster.c | 42 ++++++++++++++++++++++++++++++++ block/qcow2-refcount.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++= ++++ block/qcow2.c | 40 +++++++++++++++++++++++-------- block/qcow2.h | 2 ++ qapi/block-core.json | 3 ++- 5 files changed, 141 insertions(+), 11 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index d779ea19cf..a84b7e607e 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -32,6 +32,48 @@ #include "qemu/bswap.h" #include "trace.h" =20 +int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size) +{ + BDRVQcow2State *s =3D bs->opaque; + int new_l1_size, i, ret; + + if (max_size >=3D s->l1_size) { + return 0; + } + + new_l1_size =3D max_size; + +#ifdef DEBUG_ALLOC2 + fprintf(stderr, "shrink l1_table from %d to %" PRId64 "\n", + s->l1_size, new_l1_size); +#endif + + BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE); + ret =3D bdrv_pwrite_zeroes(bs->file, s->l1_table_offset + + sizeof(uint64_t) * new_l1_size, + (s->l1_size - new_l1_size) * sizeof(uint64_t)= , 0); + if (ret < 0) { + return ret; + } + + ret =3D bdrv_flush(bs->file->bs); + if (ret < 0) { + return ret; + } + + BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_FREE_L2_CLUSTERS); + for (i =3D s->l1_size - 1; i > new_l1_size - 1; i--) { + if ((s->l1_table[i] & L1E_OFFSET_MASK) =3D=3D 0) { + continue; + } + qcow2_free_clusters(bs, s->l1_table[i] & L1E_OFFSET_MASK, + s->l2_size * sizeof(uint64_t), + QCOW2_DISCARD_ALWAYS); + s->l1_table[i] =3D 0; + } + return 0; +} + int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size) { diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 576ab551d6..e98306acd8 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -29,6 +29,7 @@ #include "block/qcow2.h" #include "qemu/range.h" #include "qemu/bswap.h" +#include "qemu/cutils.h" =20 static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size); static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, @@ -2936,3 +2937,67 @@ done: qemu_vfree(new_refblock); return ret; } + +int qcow2_shrink_reftable(BlockDriverState *bs) +{ + BDRVQcow2State *s =3D bs->opaque; + uint64_t *reftable_tmp =3D + g_try_malloc(sizeof(uint64_t) * s->refcount_table_size); + int i, ret; + + if (s->refcount_table_size && reftable_tmp =3D=3D NULL) { + return -ENOMEM; + } + + for (i =3D 0; i < s->refcount_table_size; i++) { + int64_t refblock_offs =3D s->refcount_table[i] & REFT_OFFSET_MASK; + void *refblock; + bool unused_block; + + if (refblock_offs =3D=3D 0) { + reftable_tmp[i] =3D 0; + continue; + } + ret =3D qcow2_cache_get(bs, s->refcount_block_cache, refblock_offs, + &refblock); + if (ret < 0) { + goto out; + } + + /* the refblock has own reference */ + if (i =3D=3D refblock_offs >> (s->refcount_block_bits + s->cluster= _bits)) { + uint64_t blk_index =3D (refblock_offs >> s->cluster_bits) & + (s->refcount_block_size - 1); + uint64_t refcount =3D s->get_refcount(refblock, blk_index); + + s->set_refcount(refblock, blk_index, 0); + + unused_block =3D buffer_is_zero(refblock, s->refcount_block_si= ze); + + s->set_refcount(refblock, blk_index, refcount); + } else { + unused_block =3D buffer_is_zero(refblock, s->refcount_block_si= ze); + } + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); + + reftable_tmp[i] =3D unused_block ? 0 : cpu_to_be64(s->refcount_tab= le[i]); + } + + ret =3D bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_= tmp, + sizeof(uint64_t) * s->refcount_table_size); + if (ret < 0) { + goto out; + } + + for (i =3D 0; i < s->refcount_table_size; i++) { + if (s->refcount_table[i] && !reftable_tmp[i]) { + qcow2_free_clusters(bs, s->refcount_table[i] & REFT_OFFSET_MAS= K, + s->cluster_size, QCOW2_DISCARD_ALWAYS); + s->refcount_table[i] =3D 0; + } + } + +out: + g_free(reftable_tmp); + return ret; +} diff --git a/block/qcow2.c b/block/qcow2.c index b3ba5daa93..0ad46d2776 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2545,6 +2545,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, Error **errp) { BDRVQcow2State *s =3D bs->opaque; int64_t new_l1_size; + uint64_t total_size; int ret; =20 if (offset & 511) { @@ -2558,17 +2559,36 @@ static int qcow2_truncate(BlockDriverState *bs, int= 64_t offset, Error **errp) return -ENOTSUP; } =20 - /* shrinking is currently not supported */ - if (offset < bs->total_sectors * 512) { - error_setg(errp, "qcow2 doesn't support shrinking images yet"); - return -ENOTSUP; - } - new_l1_size =3D size_to_l1(s, offset); - ret =3D qcow2_grow_l1_table(bs, new_l1_size, true); - if (ret < 0) { - error_setg_errno(errp, -ret, "Failed to grow the L1 table"); - return ret; + total_size =3D bs->total_sectors << BDRV_SECTOR_BITS; + + if (offset < total_size) { + ret =3D qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size= ), + total_size - ROUND_UP(offset, + s->cluster_size), + QCOW2_DISCARD_ALWAYS, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to discard reduced claste= rs"); + return ret; + } + + ret =3D qcow2_shrink_l1_table(bs, new_l1_size); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to reduce the L1 table"); + return ret; + } + + ret =3D qcow2_shrink_reftable(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to shrink the refcount ta= ble"); + return ret; + } + } else { + ret =3D qcow2_grow_l1_table(bs, new_l1_size, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to grow the L1 table"); + return ret; + } } =20 /* write updated header.size */ diff --git a/block/qcow2.h b/block/qcow2.h index 07faa6dc78..600463bf8e 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -531,10 +531,12 @@ int qcow2_pre_write_overlap_check(BlockDriverState *b= s, int ign, int64_t offset, int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, BlockDriverAmendStatusCB *status_cb, void *cb_opaque, Error **errp); +int qcow2_shrink_reftable(BlockDriverState *bs); =20 /* qcow2-cluster.c functions */ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size); +int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size); int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset= ); int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, diff --git a/qapi/block-core.json b/qapi/block-core.json index f85c2235c7..bcbffa3339 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2372,7 +2372,8 @@ 'cluster_alloc_bytes', 'cluster_free', 'flush_to_os', 'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head', 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev', - 'pwritev_zero', 'pwritev_done', 'empty_image_prepare' ] } + 'pwritev_zero', 'pwritev_done', 'empty_image_prepare', + 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters' ] } =20 ## # @BlkdebugInjectErrorOptions: --=20 2.13.0