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 62F6680069 for ; Thu, 27 Aug 2026 16:11:19 +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 67RGA7sv001772; Thu, 27 Aug 2026 19:10:08 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 67RGA7sv001772 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="E5jo9DGu" Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 67RGA6UF001768 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Thu, 27 Aug 2026 19:10:07 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 67RGA6UF001768 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-482e12bb58aso5041f8f.0 for ; Thu, 27 Aug 2026 09:10:06 -0700 (PDT) X-Gm-Message-State: AFuF++lsjBprLPICk1Y0ZhCzQz2QAn84yVSOOvFPUpg0+UQAv7mbakhS jNf36jjK3sS7mwe75AkNyJBe0iGu1uJzUXdVjH5iSEnyBVg7nTQb3nfa/CuNuQhhjClpF7kyn6b 3O9S61AwAWXtLXTovF6CfpM3w4iEqkyeg49F0zI9Xjm3hhvljNy0BzQ== X-Gm-Gg: AR+sD10FwY0FhD2GNI9K0cwkh4TZdIsidufY1PeQaPNs+PEck7wILK55IB5htpKbAzi oVdheEnco25G0a857e+bzhUNLfEzISRXXFV4nj3nymkczsSUWy0MCGl7vuRUSBdiwHNrP5L3zHo eCumJmn/MrQakkWROu99U+9Akvbn2R5uGCdv/MuuiJX2lPM4uAAr2AgftglHtMhreVjK8yTRmoU trNJ5CD/lS94QUSXwT2/JmNyfYEtXYNMvNIVmcpPc18FYkOr8hJGFriilXRmw/oMHGp0ynZ4jAh /Jv/Szv8t/POsYCJihN7KS9rnvR+le2b7MBhzRUjGaqu625wDeDPIAnuP/OLdTFM1VT0FV6ZL52 37YrqYAF3NqZAttABwhqI/oKha4h+YQ== X-Received: by 2002:a05:6000:41e1:b0:482:e173:9941 with SMTP id ffacd0b85a97d-482e26ed73cmr22398785f8f.18.1787847005218; Thu, 27 Aug 2026 09:10:05 -0700 (PDT) X-Received: by 2002:a05:6000:41e1:b0:482:e173:9941 with SMTP id ffacd0b85a97d-482e26ed73cmr22398333f8f.18.1787847003358; Thu, 27 Aug 2026 09:10:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787847003; cv=none; d=google.com; s=arc-20260327; b=iG+E+IgiHESAkls2q9Wi/RZiMEEMrZ14vVyoT0O1vxynpnkKWEUK/fKiOALjTYiEFG G0taT7rOs3BNR/zKH7CetUMS/GDTgxXMhwJYAeK1mH40wElaQGZpFJligYveyeZZBw7O 7WZ8xsuL2RZxiL9K57RFpVRJQMW/T4wLiFZ8X9yjk1Smz/I3V7blNO7B/2TBX/uZC7y1 VjApS2GgzH6lQKgxz8BuPy875p9PCkjzlhuvL5OCHQWoT3WEfTA27hw+HCqCNfM0Llci 8FZAmu2DyH3q0PrO2XK1Bt1bLXYLHgMLIfYfyxumUszIgtTKCu3Trf2bEZ7DAI5wDHf6 je+A== 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=duJXvjATIM1xeNZ8gqAuHHPOEuFLsluuwRPM4Yk5UcE=; fh=0/brz1B8ohImS2ERrXZY0dPGpSEyX2H6iLC7bneXJkE=; b=FPFr39WDXEocLz8fGOjMnsvY41RoomDdO1T+3OS01oGLc7bNhkM3CLjlkWfhZ/Jal6 BPjcUDxOf+kvqHphrj4y2Km846Tq+VVfxaErEghMvKkwcrNAafMUjhf7fUgpd/o1OO0L AQ4v0T+VU+JO+Y7v4WhRwYEKDDjqOzL+3Q7fIDSt1Mdbqfv7nBY2JhFIymbwIdSP3aUu JZ4ZiI1pgnPP7F20Z8DkO/fpzn1LAeekCxdvARxvb9BVfgEhBaPpOkpLyngPEYGZTcYK IBhWe3OfPMxKohSW3Gj7Zpkow2JzalwFlodN/P3qtaMlllQiwDCTDnwN8QOkw/tEFV7t uSdg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=E5jo9DGu; spf=pass (google.com: domain of andrey.zhadchenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=andrey.zhadchenko@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-482e2787a50si8206862f8f.53.2026.08.27.09.10.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 09:10:03 -0700 (PDT) Received-SPF: pass (google.com: domain of andrey.zhadchenko@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=E5jo9DGu; spf=pass (google.com: domain of andrey.zhadchenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=andrey.zhadchenko@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=duJXvjATIM1xeNZ8gqAuHHPOEuFLsluuwRPM4Yk5UcE=; b=E5jo9DGuM9Ma edeDmQLq5clKQPKHJbz2H2O/yVLbRncKMTACM8bQvXgW2LtcFPG4n4jRqWpHQglG1Rh3Fj62/6HlT Dk1sziSg7B1ElkJ9r1ig5WAnrw20nfliddHw4+53teXn2GLIndAYm0RAEqRLEVrosU7vF8tGGf87M J9xoyYs+6cvNWmBZLc1oT4W36PabcfEEClQ0a+q1v0p4Ig+mXoFfHL9FjsCiic9Ee2NaGpwLmTFA0 zLp48zFplAUVxUq6B7Q79y38ALP6mw1uN3DNB/Fv1SIUy6wo8KXsDcmHOvPqfG3CjVsL8kxGO096I 6KmeZnSQgUzC/OXnURF22A==; Received: from [130.117.225.5] (helo=vz9-demens-1.aci.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1wzccs-00FHQJ-1h; Thu, 27 Aug 2026 18:09:08 +0200 From: Andrey Zhadchenko To: ptikhomirov@virtuozzo.com, vasileios.almpanis@virtuozzo.com Date: Thu, 27 Aug 2026 19:06:18 +0300 Message-ID: <20260827160619.303398-11-andrey.zhadchenko@virtuozzo.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20260827160619.303398-1-andrey.zhadchenko@virtuozzo.com> References: <20260827160619.303398-1-andrey.zhadchenko@virtuozzo.com> MIME-Version: 1.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH VZ10 v4 10/11] drivers/md/dm-qcow2: do discards during backward merge only for writable image 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 Backward merge discards every merged cluster from the image we merge from: the L2 entry is zeroed and refcounts are decremented, which dirties the image metadata. This requires the image file to be opened for write, while merge-in-the-middle images usually opened read-only. Skip the discard step when the merged image is read-only: - complete the merge qio right after its data is written to the lower delta, without the L1/L2 entry update; - process READs on such image in the regular way. Previously reads would cause out-of-order merge for present cluster and then requeue. Without discard it will loop. - do not break COW at L1. Note that due to how merge machinery works, we can't merge without unuse and internal snaphots (to be addressed in the next patches). - do not clear the dirty bit on merge completion: the image was never modified. Just in case add warning and end qio if we somehow encounter non-service write qio for read-only images during the merge. https://virtuozzo.atlassian.net/browse/VSTOR-138288 Feature: dm-qcow2: block device over QCOW2 files driver Signed-off-by: Andrey Zhadchenko --- v3/v4: - reorder a patch and remove a guard against images with internal snapshots drivers/md/dm-qcow2-cmd.c | 21 +++++++++++++-------- drivers/md/dm-qcow2-map.c | 27 ++++++++++++++++++++++++++- drivers/md/dm-qcow2.h | 5 +++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/drivers/md/dm-qcow2-cmd.c b/drivers/md/dm-qcow2-cmd.c index c15c46a0fe8b7..fa3762c58372b 100644 --- a/drivers/md/dm-qcow2-cmd.c +++ b/drivers/md/dm-qcow2-cmd.c @@ -264,7 +264,7 @@ static int qcow2_merge_backward_start(struct qcow2_target *tgt, int efd, u32 dep lower = qcow2->lower; if (!lower) return -ENOENT; - if (!(lower->file->f_mode & FMODE_WRITE)) + if (!qcow2_file_is_writable(lower)) return -EACCES; if (qcow2->clu_size != lower->clu_size) return -EOPNOTSUPP; @@ -315,11 +315,14 @@ void qcow2_merge_backward_work(struct work_struct *work) * there would be problems with unusing them: * we'd have to freeze IO going to all data clusters * under every L1 entry related to several snapshots. + * Readonly images skip this stage. */ - ret = qcow2_break_l1cow(tgt, qcow2); - if (ret) { - QC_ERR(tgt->ti, "Can't break L1 COW"); - goto out_err; + if (qcow2_file_is_writable(qcow2)) { + ret = qcow2_break_l1cow(tgt, qcow2); + if (ret) { + QC_ERR(tgt->ti, "Can't break L1 COW"); + goto out_err; + } } backward_merge_update_stage(tgt, BACKWARD_MERGE_STAGE_SET_DIRTY); @@ -388,9 +391,11 @@ static int qcow2_merge_backward_complete(struct qcow2_target *tgt) qcow2_flush_deferred_activity(tgt, qcow2); /* Delayed md pages */ qcow2->lower = NULL; - ret = qcow2_set_image_file_features(qcow2, false); - if (ret < 0) - QC_ERR(tgt->ti, "Can't unuse merged img (%d)", ret); + if (qcow2_file_is_writable(qcow2)) { + ret = qcow2_set_image_file_features(qcow2, false); + if (ret < 0) + QC_ERR(tgt->ti, "Can't unuse merged img (%d)", ret); + } qcow2_destroy(qcow2); tgt->backward_merge.state = BACKWARD_MERGE_STOPPED; diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c index b69f8ae106d1f..2661ceeea8d21 100644 --- a/drivers/md/dm-qcow2-map.c +++ b/drivers/md/dm-qcow2-map.c @@ -2701,6 +2701,12 @@ static void backward_merge_write_complete(struct qcow2_target *tgt, struct qio * return; } + /* Skip discard for read-only source images */ + if (!qcow2_file_is_writable(qcow2)) { + qio_endio(qio); + return; + } + WARN_ON_ONCE(qio->flags & QIO_IS_DISCARD_FL); qio->flags |= QIO_IS_DISCARD_FL; @@ -2744,6 +2750,17 @@ static int prepare_backward_merge(struct qcow2 *qcow2, struct qio **qio, struct qio *aux_qio; int ret; + /* Readonly image mappings remain stable, so reads just go through */ + if (!qcow2_file_is_writable(qcow2)) { + if (!op_is_write((*qio)->bi_op)) + return 1; + if (WARN_ON_ONCE(!fake_merge_qio(*qio))) { + (*qio)->bi_status = BLK_STS_IOERR; + qio_endio(*qio); + return 0; + } + } + if (!map->data_clu_alloced) { /* Strange COW at L1, except the merge from RO image */ WARN_ON_ONCE(map->clu_is_cow && qio_may_modify_image(qcow2, *qio)); @@ -3654,7 +3671,15 @@ static void process_one_qio(struct qcow2 *qcow2, struct qio *qio) if (!handle_metadata(qcow2, &qio, &map)) return; - if (unlikely(qcow2->backward_merge_in_process)) { + /* + * Merge machinery makes out of order merges for present + * clusters when it sees the reads. But if the merge does + * not discard the cluser mapping, it will spin endlessly. + * So process only actual merge qios or reads from writable + * images. + */ + if (unlikely(qcow2->backward_merge_in_process) && + (fake_merge_qio(qio) || qcow2_file_is_writable(qcow2))) { submit_top_delta_read(&map, qio); return; } diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h index 0f006f1ae48cc..d9b8c38e093f5 100644 --- a/drivers/md/dm-qcow2.h +++ b/drivers/md/dm-qcow2.h @@ -460,6 +460,11 @@ static inline bool qcow2_wants_check(struct qcow2_target *tgt) return !!(tgt->md_writeback_error|tgt->truncate_error); } +static inline bool qcow2_file_is_writable(struct qcow2 *qcow2) +{ + return qcow2->file->f_mode & FMODE_WRITE; +} + static inline void remap_to_clu(struct qcow2 *qcow2, struct qio *qio, loff_t clu_pos) { qio->bi_iter.bi_sector &= (to_sector(qcow2->clu_size) - 1); -- 2.43.5 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel