From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (unknown [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 2A3AD80726 for ; Thu, 8 Oct 2026 07:40:12 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6987cvmF021062; Thu, 8 Oct 2026 10:38:58 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6987cvmF021062 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="lWbPnx2e" Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6987ciNQ021019 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Thu, 8 Oct 2026 10:38:45 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6987ciNQ021019 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-48b00febba3so3350073f8f.1 for ; Thu, 08 Oct 2026 00:38:45 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvBxTZJK7bhGCmBKe8kOKbv+3O+Ov/VWBlqZaJFkovguDePnEvtJmuScZU7Bdg5Ik1jz5RiWI1g==@openvz.org X-Gm-Message-State: AFuF++lAUkEydqVlSRWEc9fNiCDHGyDFCv0n2At/K8d17jNyVfdH7+yj wm1mN7wV5V3s/j5McgZRTP/owptVFipDmVHRzj8AM84f1/GhjiTznL0WOzf1iZSPX2m5AAbFsFG yn/KI58+RWJfvIjAq67HefTbYETFdq+l6po9GDRGNRrsqeH6qK2yN0w== X-Gm-Gg: AYBFou0cNYA/9qP06wOwnXQx+IlArQbHScr7fZz7Z9qhHl9+dxO8ggF8sL1upjpVoMH 8AsgVRBW9zsyiG4IwcsUB4q8kLFiTxqF9fAPvjOsNeWkcKEAGz+IYhJhtze4p1hfsC159qHen+9 0WdQp52OlBH+a5OvGaxtyxilPZulhWqyHcVG6FAc7PHi/76RvdJ7+ESo39xveo9Yfbsb1us4uKC vz0F6OfNVbGn6sW495sXP2NfRKK9f+rqInredwK14MUqIOmAi/sLczeIb3G8GlMJZcoIp4lJjrp +lrb2X+tIlkG6y7WJJwCt5xdoh+WvpK1phBH0lkp+zHGks3qyAe3kYhZ79daRwqYWinqqhSOKZm /dDzctBfk1Zh0uSFjmTeqPLxEAnM= X-Received: by 2002:a05:600c:19d0:b0:4a0:1f51:ba2d with SMTP id 5b1f17b1804b1-4a18045373dmr74604965e9.22.1791445124599; Thu, 08 Oct 2026 00:38:44 -0700 (PDT) X-Received: by 2002:a05:600c:19d0:b0:4a0:1f51:ba2d with SMTP id 5b1f17b1804b1-4a18045373dmr74604535e9.22.1791445123999; Thu, 08 Oct 2026 00:38:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1791445123; cv=none; d=google.com; s=arc-20260327; b=s85LITRCak5MRYR6kEpPV8halzKXdJgpUYeXTNXHKYh7s5eJiwHdPFFmINfdzzBAfi gbYTNALRFEorXbdbuN+67Wr7CHhVdvsFNjFw6I1qLs3Qur96UfIcGeCPqmP0i6cz+0p6 5lqKPkY9JVcWniuhR3yls/QkZvhsFYtaGvA7i1QjK7/hA55tAsLHJ9SkMiuHmlHzS8wI nrAsbQsb1MBNDNlgZsk9k8EElLMFcPKYnb3MsK7NB4UWzsfKf17cAQoVNvay+R1vUJZ7 0dXb9N1q9umoUMVYw1+MwkF3JWZnd67uXqWLKKjysK83pbzZivjOG0AL7ptaB4PWiRiU OhTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=j6HARKyObi+vQm/+MFtWS2D5A2o6VAwOxQhCZhJ7UiU=; fh=iR+h9bi3Bh9zMcmhT/g9qNPJn2rboPnO22cA9JfMqyc=; b=fL8HDYLsOMgjuvc0WR2Tu+NcFOZdEveC/85RZvtlGf/3D0LaxtWdHJbcF+xNfrTM7h ihm/w3ee45GQHWK/mrm421et8FIMZ5dJkMTbJCWue1V7LG6sTsip8YME9//XeBq02y/N 6kWowIIUry3TsYkh26GTYzhU8IxDtSYM4jGZZ2/EGaf4xZuA7+yRzqqZX0Hza81Dmrij L2ozRU8SMdXpYNmxFRwrdKZkxRjKwKo3R7+g7MDdunn/YgQoO/sfNo5L2FepnEbRa42v sxW5TMrZCbqGt1n6K5KNzUHI0IUdjYPk7OE4kW0c5w/aEr2xpoH5fVR6IXSIRypKfrck HjiA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=lWbPnx2e; spf=pass (google.com: domain of alexander.ivanov@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=alexander.ivanov@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id ffacd0b85a97d-48c7247bf00si9281917f8f.213.2026.10.08.00.38.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Oct 2026 00:38:43 -0700 (PDT) Received-SPF: pass (google.com: domain of alexander.ivanov@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=lWbPnx2e; spf=pass (google.com: domain of alexander.ivanov@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=alexander.ivanov@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-ID:Date:Subject:From: Content-Type; bh=j6HARKyObi+vQm/+MFtWS2D5A2o6VAwOxQhCZhJ7UiU=; b=lWbPnx2erBwl R7RE3m2S1/l5WAl/mMmCE2KdCm+H+0LARmi+jtomPT0HbdJAa/2FfmctYTbKP/vONMv6dtxhRV0l5 E7Ez43IlkCleOH8QFTJS1wKvvPd97WmbI+PMUX/BKS4B7Ms+4JKxrqDjTE4cUn1EWGauMyutcK8QT HMUU1SOi3Emar/mrlJVy9VmIoURmvksp3uglyqZ3Szt831l768cvd1fw5z3XgRr7C1oDIq+OuO2sj DTn79y36DCo2SzFwftILcfAvz1fyV5a/kPMcJLEi/RKMDMjZBRUVS2xVrvxh3PC7es3tZ1S64Yo3p iAjGuEDtdNHejF1R8cC/Vg==; Received: from ch-vpn.virtuozzo.com ([130.117.225.6] helo=sky) by relay.virtuozzo.com with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1xEieu-007naT-0m; Thu, 08 Oct 2026 09:38:41 +0200 From: Alexander Ivanov To: den@virtuozzo.com Date: Thu, 8 Oct 2026 09:38:32 +0200 Message-ID: <20261008073837.510678-3-alexander.ivanov@virtuozzo.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261008073837.510678-1-alexander.ivanov@virtuozzo.com> References: <20261008073837.510678-1-alexander.ivanov@virtuozzo.com> MIME-Version: 1.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v2 2/6] dm-qcow2: truncate unused tail of image on suspend X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org On postsuspend we truncate the image file only down to file_preallocated_area_start, i.e. we drop preallocations only. Clusters at the end of the file freed by discard (refcount dropped to zero) are never given back, so the file size never shrinks. Add qcow2_calc_used_end(), which scans refcount blocks backward from file_preallocated_area_start and returns the end of the last cluster with non-zero refcount. Refcount ranges with no allocated refblock are skipped at once. Metadata pages are taken from md cache or read synchronously. This is called on suspended device after md writeback, so R1 and R2 can't change under us. Truncate the file to the used end. Skip the scan if md writeback failed, as refcounts on disk are stale then, and fall back to the old behaviour on scan error. https://virtuozzo.atlassian.net/browse/VSTOR-148171 Feature: dm-qcow2: block device over QCOW2 files driver Signed-off-by: Alexander Ivanov --- drivers/md/dm-qcow2-map.c | 53 ++++++++++++++++++++++++++++++++++++ drivers/md/dm-qcow2-target.c | 12 +++++++- drivers/md/dm-qcow2.h | 1 + 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c index 78ee7cf5e881..7f2ffe7b2405 100644 --- a/drivers/md/dm-qcow2-map.c +++ b/drivers/md/dm-qcow2-map.c @@ -2208,6 +2208,59 @@ int qcow2_truncate_safe(struct file *file, loff_t new_len) return do_ftruncate(file, new_len, 0); } +/* + * Returns the end of the last cluster, which is used according + * to refcount table. Clusters freed by discard may leave the tail + * of file unused. Everything at or above file_preallocated_area_start + * is unused by construction, so the scan starts below it. This must be + * called on suspended device after md writeback, so nobody changes + * R1 and R2. + */ +loff_t qcow2_calc_used_end(struct qcow2 *qcow2) +{ + u32 clu_size = qcow2->clu_size; + struct qcow2_map_item r1, r2; + struct md_page *r1_md = NULL; + loff_t pos; + s32 i; + int ret; + + pos = round_down(qcow2->file_preallocated_area_start - 1, clu_size); + while (pos >= 0) { + if (calc_refcounters_map(qcow2, pos, &r1, &r2) < 0) + return -EIO; + + if (!r1_md || r1_md->id != r1.page_id) { + ret = qcow2_md_page_read_sync(qcow2, r1.page_id, &r1_md); + if (ret) + return ret; + } + r1.md = r1_md; + + ret = calc_r2_page_id(qcow2, &r1, &r2); + if (ret == -ENOENT) { + /* No R2 cluster, so all clusters it covers are unused */ + pos = (loff_t)r1.index * qcow2->refblock_entries * clu_size; + pos -= clu_size; + continue; + } + + if (ret < 0) + return ret; + + ret = qcow2_md_page_read_sync(qcow2, r2.page_id, &r2.md); + if (ret) + return ret; + + for (i = r2.index_in_page; i >= 0; i--, pos -= clu_size) { + if (get_r2_entry(qcow2, r2.md, i)) + return pos + clu_size; + } + } + + return -EIO; +} + static int truncate_prealloc_safe(struct qcow2 *qcow2, loff_t len, const char *func) { loff_t prealloc_len, max_prealloc_len = qcow2->reftable_max_file_size; diff --git a/drivers/md/dm-qcow2-target.c b/drivers/md/dm-qcow2-target.c index 3e47e66b4007..3cbec3b9b407 100644 --- a/drivers/md/dm-qcow2-target.c +++ b/drivers/md/dm-qcow2-target.c @@ -1042,11 +1042,21 @@ static void qcow2_truncate_preallocations(struct dm_target *ti) { struct qcow2_target *tgt = to_qcow2_target(ti); struct qcow2 *qcow2 = top_qcow2_protected(ti); - loff_t end = qcow2->file_preallocated_area_start; + loff_t used_end, end = qcow2->file_preallocated_area_start; int ret; if (!(dm_table_get_mode(ti->table) & FMODE_WRITE)) return; + + /* Refcounts on disk are stale after failed md writeback */ + if (!tgt->md_writeback_error) { + used_end = qcow2_calc_used_end(qcow2); + if (used_end < 0) + QC_ERR(ti, "dm-qcow2: Can't find used end: %lld", used_end); + else + end = used_end; + } + if (end == qcow2->file_size) return; diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h index 69d3ae6fca8a..73d3cf175bbf 100644 --- a/drivers/md/dm-qcow2.h +++ b/drivers/md/dm-qcow2.h @@ -411,6 +411,7 @@ void qcow2_ref_dec(struct qcow2_target *tgt, u8 ref_index); int qcow2_inflight_ref_switch(struct qcow2_target *tgt); void qcow2_flush_deferred_activity(struct qcow2_target *tgt, struct qcow2 *qcow2); int qcow2_truncate_safe(struct file *file, loff_t new_len); +loff_t qcow2_calc_used_end(struct qcow2 *qcow2); void qcow2_merge_backward_work(struct work_struct *work); void qcow2_merge_backward_cancel(struct qcow2_target *tgt); -- 2.53.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel