From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (mail.openvz.org [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 5538D8146A for ; Mon, 9 Nov 2026 14:03:46 +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 6A9E2VK8032604; Mon, 9 Nov 2026 17:02:32 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A9E2VK8032604 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="lutlJ4GU" Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A9E1m2p032524 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Mon, 9 Nov 2026 17:01:49 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A9E1m2p032524 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-48e0461e040so809832f8f.0 for ; Mon, 09 Nov 2026 06:01:49 -0800 (PST) X-Forwarded-Encrypted: i=2; AL+hErHPBMvYFPFVpNlQtozYQVLL4b/pMis+Nhj3DH5Lm2nlfBq7ixLC8kmUGA31puoi+vfVyetTVg==@openvz.org X-Gm-Message-State: APuU4Z/zyHYTlBQgjCs+qDyvxPuRuR/GBaUYvC+7JS3468S7y9cRl3ZY Ot6DSJLN9h0uVm/KMVLH3UA4HeQSMJZvZo2M4uYXqnZh5YJGTXzlqjSAJhc8Z+a/NfBpxRAXOgq O/l+9rb2YbhoxO3daOOrmKSfME41IP98wm3Vr11RR5pT16DnxT4EpYw== X-Gm-Gg: AYBFou2EdHxlg6IG7xS7JRZ+N7JPxcs1bmG+5MpNxFBz7ZHS1Ptva3CRMWRjfmmABts mqcoiTa7J5zCt827V1Jb1Jm6tmu/2snLGu+tx4MZ7F/sNSwUnfNkfQ22dt2Zq84xyprabpjacFn OlgXmJvW3fJrYWZSnnY3OD4TZuOpR5rBG0Ot78qTp/cQesfWyhSYZyLWy37DXMHd4VipDGtiydN 8dYb0f71tlsn1RyO0jtuEaYNDlUeXbWkfqpjauoNjYeZcVonGr25E1GQfdYZ2dhhxqjB7Nqvsel v/yeOVbUK0BWNwrKebTYd5y92/SpGUj4PgecrKNU/IuACj0II7Od7DZP/I2K0O7dXtQvN26nUyN 3SJ6UWhjDvltpfPp9FFbamS0JKWxe X-Received: by 2002:a05:6000:26c6:b0:492:b880:53a7 with SMTP id ffacd0b85a97d-49580830840mr8011455f8f.5.1794232908471; Mon, 09 Nov 2026 06:01:48 -0800 (PST) X-Received: by 2002:a05:6000:26c6:b0:492:b880:53a7 with SMTP id ffacd0b85a97d-49580830840mr8011388f8f.5.1794232907720; Mon, 09 Nov 2026 06:01:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1794232907; cv=none; d=google.com; s=arc-20260327; b=kkwW8hxy/pEriDEMGeE5UV81QqR5RDbFy+LBC5Myvluoc8M5ygmfmeCvvWGnQEuIeY A2Dz380N/v1uvp5+97pCuc4xeAc/VGv8QykLBnOyYoqb/0PaRhTRUFgZFjxcl7rDfOJW wWjBFtgvaTSkOWTlkuL0UVpgWBKtLCqPkL8ki6CYD3/V3ylbc2AM8lFCi900QFqY89Mt fdJsLoDgriKm3Qw8AuIJdKyGjacfmsmnIHIp44JY/jR3JF4wsZvzhLBrs1voh2uWINng QL0uQPByI9vjLDIXbX4xR/B5meAbikSeOdk3yGOnCT7ehEmDJuNOua0mFZzK6zcFsds0 CQuA== 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=6jlkT8Rir9wybkFdT8VeEhYjI2olkTaPbwf2/LedZO0=; fh=CMILZ+goaghq6B4UpCDhf0EQp6kYD0LAlmOkUiVCOvs=; b=nHlgO6LXmXfdgQDP9ewqDVAiuB1hXCRfw46JPVPfojLX4ivNKRvRygbH+tfdIw0yN0 ZUUBWyuW1+EpdY9GmoqF8pqTCxkiVOo83rRDaYiA2bITixgF6TfE5K88gBfGYcjIoJtt vRdzoxl+udHnSMFuc+7OhdW2kyrP0AL77Wn8kUJrOQg9Pao+PM/vAYzT2dIabGHWxKa2 eI0du/jqcGUJcrKnccESUWckN5AcFISPNE5TSr4vthl+SCZurNAqZIcz42t0L/ag4hUe pMQFq/k5C/2m9E4s/MVLwVhPUcd7opx4v6S7YFTkV2IIu7fn/ELvEDRAZSSa169qYNzQ k8vg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=lutlJ4GU; 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-495984b8dd6si8416541f8f.356.2026.11.09.06.01.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 06:01:47 -0800 (PST) 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=lutlJ4GU; 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=6jlkT8Rir9wybkFdT8VeEhYjI2olkTaPbwf2/LedZO0=; b=lutlJ4GUeKgt AF/KnEWUiBTGtFWrng9d+k/d7Lycf46aTsyTAXrv/tJ+wHuWvB13Vlkp/E3mqLENCxeB1TG0aSjih kweRClV/00VSirZJi7mZQHXaPbG5Bf8k4efd1xYk/OYaMjckOCUXLEQ1LOPE5M9UIRt/evY/o38W1 3EbM8ILxI7lHXRpZ6iEcbMISV31DAZEfxhXCUGZH1PUqIh14b2KftkRCpEwYdg2RpCQyg8v4+Hkg5 Qhm2itYMif2ef8HqLmTFthwYekv8hRAiDzcZBhLBaT0YbvzRgRtbVvUnCuZLmsFJli/QbK9om+3mb uN9xzH3qwD5xRR03I8mPfA==; 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 1xQPsM-005vFF-22; Mon, 09 Nov 2026 15:01:38 +0100 From: Alexander Ivanov To: andrey.zhadchenko@virtuozzo.com Date: Mon, 9 Nov 2026 15:01:41 +0100 Message-ID: <20261109140143.1408038-9-alexander.ivanov@virtuozzo.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261109140143.1408038-1-alexander.ivanov@virtuozzo.com> References: <20261109140143.1408038-1-alexander.ivanov@virtuozzo.com> MIME-Version: 1.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v11 08/10] dm-qcow2: leak clusters allocated for a failed L1/L2 writeback 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 A failed L1/L2 writeback reverts the page in memory and frees each cluster allocated for it: revert_l_entries_update() drops the refcount of a newly allocated cluster, and a COW qio waiting on the page frees its cluster through FREE_ALLOCATED_CLU when it ends with the error. The write may still have partially reached the disk, so L1/L2 on disk may point to such a cluster. Until the page is rewritten, the allocator may give the cluster to another offset, and two guest offsets then share it. If the page is not rewritten before suspend, the image is left with a reference to a free cluster. Keep the refcount of these clusters instead. If L1/L2 on disk points to such a cluster, the image stays consistent; otherwise the cluster is leaked, which check repairs by freeing it. So the image needs no check and resume needs no refusal. https://virtuozzo.atlassian.net/browse/VSTOR-148171 Feature: dm-qcow2: block device over QCOW2 files driver Fixes: 222b6f1291c1c ("dm-qcow2: Introduce driver to create block devices over QCOW2 files") Signed-off-by: Alexander Ivanov --- drivers/md/dm-qcow2-map.c | 51 +++++++----------------------------- drivers/md/dm-qcow2-target.c | 4 --- 2 files changed, 9 insertions(+), 46 deletions(-) diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c index 995f611ae5bb..4ab8051f08c4 100644 --- a/drivers/md/dm-qcow2-map.c +++ b/drivers/md/dm-qcow2-map.c @@ -1331,50 +1331,15 @@ static void do_md_page_read_complete(int ret, struct qcow2 *qcow2, /* Be careful with dirty_or_writeback()/etc! Check races. */ static void revert_l_entries_update(struct qcow2 *qcow2, struct wb_desc *wbd) { - struct qcow2_map_item r1, r2; - struct page *pe_page; - bool skip_odd; - u64 pos, old; - bool cleared; - int i, ret; - - skip_odd = qcow2->ext_l2 && wbd->lx_level == L2_LEVEL; + struct page *pe_page = wbd->pe_page; + u64 old; + int i; lockdep_assert_held(&qcow2->md_pages_lock); for_each_set_bit(i, wbd->changed_indexes, LX_INDEXES_PER_PAGE) { - pos = get_u64_from_be_page(wbd->md->page, i); - - cleared = !(pos & ~(u64)L2_READS_ALL_ZEROES); - /* Here we restore prealloced and compressed clu mappings */ - pe_page = wbd->pe_page; - if (pe_page) { /* Only L2 has this. */ - old = get_u64_from_be_page(pe_page, i); - if (old != 0) { - set_u64_to_be_page(wbd->md->page, i, old); - continue; /* Avoid mark_cluster_unused() */ - } - } - - set_u64_to_be_page(wbd->md->page, i, 0); - if (skip_odd && (i & 1)) - continue; /* pos contains ext_l2 part of L2 entry */ - if (cleared) - continue; /* no cluster was allocated */ - - spin_unlock(&qcow2->md_pages_lock); - pos &= ~LX_REFCOUNT_EXACTLY_ONE; - - /* - * R1/R2 should be cached, since we was able - * to submit cluster allocation. - */ - ret = qcow2_handle_r1r2_maps(qcow2, pos, NULL, &r1, &r2, false); - if (WARN_ON_ONCE(ret <= 0)) - continue; - - mark_cluster_unused(qcow2, r2.md, r2.index_in_page, pos); - spin_lock(&qcow2->md_pages_lock); + old = pe_page ? get_u64_from_be_page(pe_page, i) : 0; + set_u64_to_be_page(wbd->md->page, i, old); } } @@ -1408,6 +1373,7 @@ static void complete_wbd(struct qcow2 *qcow2, struct wb_desc *wbd) LIST_HEAD(wait_list); LIST_HEAD(end_list); unsigned long flags; + struct qio *qio; spin_lock_irqsave(&qcow2->md_pages_lock, flags); revert_l_entries_update(qcow2, wbd); @@ -1415,6 +1381,8 @@ static void complete_wbd(struct qcow2 *qcow2, struct wb_desc *wbd) &wait_list, &end_list); spin_unlock_irqrestore(&qcow2->md_pages_lock, flags); + list_for_each_entry(qio, &end_list, link) + qio->ext->cleanup_mask &= ~FREE_ALLOCATED_CLU; qcow2_dispatch_qios(qcow2, NULL, &wait_list); end_qios(&end_list, errno_to_blk_status(wbd->ret)); } @@ -1445,8 +1413,7 @@ static void do_md_page_write_complete(int ret, struct qcow2 *qcow2, /* * We can finish wb only in case of success. * Otherwise this is done in finalize_wbd() - * after data qios stopped use wbd clusters - * and clusters allocations reverted. + * after data qios stopped use wbd clusters. */ if (likely(ret == 0)) { clear_writeback_status(qcow2, md, ret, diff --git a/drivers/md/dm-qcow2-target.c b/drivers/md/dm-qcow2-target.c index 6824d95193ae..99fb68a5535e 100644 --- a/drivers/md/dm-qcow2-target.c +++ b/drivers/md/dm-qcow2-target.c @@ -173,10 +173,6 @@ void qcow2_flush_deferred_activity(struct qcow2_target *tgt, struct qcow2 *qcow2 struct md_page *md; int i; - /* - * We need second iteration, since revert_l_entries_update() - * may start timer again after failed wb. - */ for (i = 0; i < 2; i++) { if (timer_delete_sync_try(&qcow2->slow_wb_timer) != -1) qcow2_slow_wb_timer_fn(&qcow2->slow_wb_timer); -- 2.53.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel