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 B555C80474 for ; Wed, 28 Oct 2026 14:56:24 +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 69SEt4K4020890; Wed, 28 Oct 2026 17:55:05 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69SEt4K4020890 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=default; t=1793199307; bh=u/K6AWolyFKa4jye8rCGFeLf5qthamsT2xLqRXJHmsU=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe; b=u8VlZdVJXuZczR6tG6QwDq5X5HKnGa2cNmx8B+Mfuz3dz3OLHXKA28AHi8UDWICHv s4FMNQ77b6UtY0aMF6E+dgJED2gHdSxtpKeoJ7NjJPO3TyItQQ4zpVX7Sy+LwHm2pl pqXX5JaIwb/hnlHy+qjebFIwuN9ab+7ViOWbQMSvecLv608cy/JW1lewxalJO5dVXv mGCGPBitvWWLK21gT7c8A8UAgMQY/y6PTI5s3EHooRn/eSIeeDXVOpWNL4MNpnk+ek T6DpC7JW/RavT/pZloO6SG2W1RRGIHTPhq/6VpTn0qd6s3CCZenFSFTqzho/2wMJj5 9a0G24XWnT7xA== Received: from mail-lf1-f71.google.com (mail-lf1-f71.google.com [209.85.167.71]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 69SEt3tf020886 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Wed, 28 Oct 2026 17:55:03 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69SEt3tf020886 Authentication-Results: mail.openvz.org; dkim=pass (2048-bit key) header.d=openvz.org header.i=@openvz.org header.b="QvrgLubC" Received: by mail-lf1-f71.google.com with SMTP id 2adb3069b0e04-5bcef0c8b58so674658e87.0 for ; Wed, 28 Oct 2026 07:55:03 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvByozILbo1q31yUdTRvQSeWU08MdN5pU0Vfe5bqrIZwqP7D7rxai1FOUih2JYFUT4jOL8jb0yg==@openvz.org X-Gm-Message-State: AFq9FYKZsxu9/K0rxskX3PR1yxjRq2BlYGbrWytMBV5SsaIMne0I9qDN X2eVinxmYFCdyWF5ZupljwuFJG4t41p2eUuqqRQHavL/ZAdPh01RGMSn0FGe81k/KfGzGZfkE3M d2wp6ye7OiyowOaXNCaBLxpwQ0Uds96I7LV6K3K7nmWx/mVZyk2LMnQ== X-Gm-Gg: AYBFou2kZ0fJv09tXS967fmo1AZWFPSqQ0pMjaaPOvD3TB0S+lP8WawZg4usGV6Nd9N tW1s9OrfySTqimOXjpLed+5C3YXfEl5omDEnwPqc0ZhCpgwnKYautp/b6EtyiH80eGsDt8vcQE8 NJh4PzkZzS6bSds43Gn3Z8N7eeKhRJJKHqfpQobXKlYRsALNE9fmCBdSh+1/MK8KNZ7PLHn/7oq kaRlBJ6FBf8mIX2w128l9KEImLGMZOg4UC6gFQYBd9b2gsxei+egpKBqaNtcik02+dZH5FzYfgS zclUhUvsRw== X-Received: by 2002:a05:600c:1391:b0:49f:e701:51c8 with SMTP id 5b1f17b1804b1-4a966c41a4emr53916415e9.9.1793198215329; Wed, 28 Oct 2026 07:36:55 -0700 (PDT) X-Received: by 2002:a05:600c:1391:b0:49f:e701:51c8 with SMTP id 5b1f17b1804b1-4a966c41a4emr53915725e9.9.1793198214860; Wed, 28 Oct 2026 07:36:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1793198214; cv=none; d=google.com; s=arc-20260327; b=SS75cJD96COmtvZ6dL7MtHftc1EwuPQFChTbWRcPZk2BUtZQ61At9TIHdoHNZv7irJ kKgXY2esxUwGvzMJb1PNrqptkbHMfMQ79qeapJHkb5BMcUenqBnHA0/ouxcC59QiNFuE fRKir9umQzXSUMG4elRwyEDiLN5+8LhPox/8rcqK9ZhWjii6EGLo9HH4UF58qvc5SQYY ZqTQPeu4CggwQszIXJ6ORf+s0j0yKnfuKflXxpNvElu1/GRfp2VB5XoCHg9iXRAPkmaq ni9HQWNSteu7/4chpNaJgkx1bn6RHlSc3UkZ0+RXGItEZOrZoqPllME1BBNyUxc70mzK W2fw== 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=5WrdiuLihtr9tjpjhQkCWa/OvxZErW98rRE9ZrRNasc=; fh=o9n8WdQ598aUgwhbA1Ugt32UP+e1WbjSh2k7AdRrf5w=; b=jc24KuLK15Jgmf9y4dn/IpLW0Id/z6qb88xCgvcow6mJJLgcBv2P9xZ9htLUvvj3oX 34A+VIFZYbdl/Pn45xYdw9219Uzi+UTTox4Y/VRWyqOg1aQ6SvMWCQ3K13473fQCB4NK aShhXCKia8NCaBwPXA2zKQ+GjiCSYHuMmD1dn89BZPlVP5e4TmIS4CkBjd73gaVFGPxs AGWNrxQ1pkqjyX0BbUDezS5sVTKAzxYTEDUrDPT4rVq9Lj+DKuvewxbP4zPT5nwvex3S x9i1RaKetV9PTrxC+oclbUmLM/PgTNd0Y9zDo0cgGWSLgh5kYyMlFhEKbIOdA+htQNU6 KZNw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@openvz.org header.s=google header.b=QvrgLubC; spf=softfail (google.com: domain of transitioning den@openvz.org does not designate 2a06:5b06:b600:300:2c3:d099:6fb:56cf as permitted sender) smtp.mailfrom=den@openvz.org; dara=neutral header.i=@openvz.org Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id 5b1f17b1804b1-4a90da7eb4csor3805735e9.4.2026.10.28.07.36.54 for (Google Transport Security); Wed, 28 Oct 2026 07:36:54 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning den@openvz.org does not designate 2a06:5b06:b600:300:2c3:d099:6fb:56cf as permitted sender) client-ip=2a06:5b06:b600:300:2c3:d099:6fb:56cf; Authentication-Results: mx.google.com; dkim=pass header.i=@openvz.org header.s=google header.b=QvrgLubC; spf=softfail (google.com: domain of transitioning den@openvz.org does not designate 2a06:5b06:b600:300:2c3:d099:6fb:56cf as permitted sender) smtp.mailfrom=den@openvz.org; dara=neutral header.i=@openvz.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1793198214; x=1793803014; darn=openvz.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5WrdiuLihtr9tjpjhQkCWa/OvxZErW98rRE9ZrRNasc=; b=QvrgLubCyeBjH+sE9z3kMte4Fxi+eNatMlVOcR5zebnQXvp6INPJ+1qzpiHDLzNMqG DhTmCMYHCztgG8u9VHmXfiFVK9jyrh2NZ3O1aNeAyQu/THpf7pJ0bKMD6xLcAKejf6Aa l131jUQrFQ4W3RFtYyjNSd+ujKGSu3EIoD9HR4fPv3TtOQp7icORP6mIBd2mtdBBLpPg Ccx/Pd1CYPB+HSO1iK6wF+QZPu3hSxhTf6I9XnFO3HibqlCfDh0zUKe1MIpem+wVxbB8 A59P28kUAqSs6owttmypsjSBYb1+yx7sZ7BkmksICJ8YvjW8kiiCLMml11d5MXtSQP3d 8WFg== X-Forwarded-Encrypted: i=1; AKwUvByFtaggBkxP1es6l4mZTE4878+n4sOnSpIQ5QUoymze2LqVVuTyYuD2+m89vBBL7l0zeCmG9Q==@openvz.org X-Received: by 2002:a05:600c:154d:b0:4a3:5a42:b2a4 with SMTP id 5b1f17b1804b1-4a96720266bmr58342915e9.12.1793198214354; Wed, 28 Oct 2026 07:36:54 -0700 (PDT) Received: from athena.sw.ru ([2a06:5b06:b600:300:2c3:d099:6fb:56cf]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48e3ebd4d8dsm30321335f8f.36.2026.10.28.07.36.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2026 07:36:53 -0700 (PDT) From: "Denis V. Lunev" To: andrey.zhadchenko@virtuozzo.com Date: Wed, 28 Oct 2026 15:36:47 +0100 Message-ID: <20261028143647.2972030-5-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261028143647.2972030-1-den@openvz.org> References: <20261028143647.2972030-1-den@openvz.org> MIME-Version: 1.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v2 4/4] dm-ploop: fix lost BAT updates when alloc and discard share a 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 From: Denis V. Lunev Since "dm-ploop: fix and rework md updates" any update of a BAT page joins the pending index writeback of that page, whatever type it was prepared with. On completion ploop_advance_local_after_bat_wb() still applied the written page by type: a DISCARD writeback copied back only entries that became zero, an ALLOC one only non-zero entries. A first write to a cluster that joined a pending DISCARD writeback was acknowledged with its new mapping on disk but not in the local BAT. It read back as zeroes, the next write to the cluster allocated another one, and the next writeback of the page stored that, leaking the cluster with the acknowledged data. A discard that joined an ALLOC writeback left the local BAT mapped while disk had zero, so data written to that cluster afterwards was lost on the next open. Apply the changes of the pios attached to the writeback instead: the allocating data pios and COW pios set their entries, the discard pios clear theirs, other entries are left alone. The relocation on grow changes an entry that no pio stands for, so its writeback records that entry to be applied the same way. On failure the same rule as before frees only what this writeback allocated: a data pio may find its cluster already mapped by an earlier writeback. Entries nobody changed no longer get their level reset to the top one; nothing needs that once the merge of the latest snapshot renumbers the levels itself. Fixes: ddf38fa44df4 ("dm-ploop: fix and rework md updates") https://virtuozzo.atlassian.net/browse/VSTOR-151979 Signed-off-by: Denis V. Lunev Reviewed-by: Andrey Zhadchenko Feature: dm-ploop: ploop target driver --- drivers/md/dm-ploop-map.c | 133 ++++++++++++++++++++------------------ drivers/md/dm-ploop.h | 1 + 2 files changed, 71 insertions(+), 63 deletions(-) diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c index 2f8abfa8905b..016be97caaa8 100644 --- a/drivers/md/dm-ploop-map.c +++ b/drivers/md/dm-ploop-map.c @@ -86,6 +86,7 @@ void ploop_index_wb_init(struct ploop_index_wb *piwb, struct ploop *ploop) piwb->page_id = PAGE_NR_NONE; piwb->type = PIWB_TYPE_ALLOC; piwb->flush_pio = NULL; + piwb->reloc_clu = BAT_ENTRY_NONE; } void ploop_init_pio(struct ploop *ploop, unsigned int bi_op, struct pio *pio) @@ -802,73 +803,85 @@ static void ploop_complete_cow(struct ploop_cow *cow, blk_status_t bi_status) kmem_cache_free(cow_cache, cow); } +static void ploop_advance_allocated(struct ploop *ploop, struct md_page *md, + map_index_t *dst_clu, u32 clu, bool success) +{ + u32 i = ploop_bat_clu_idx_in_page(clu); + u32 *bat_entries = md->kmpage; + u32 new_clu = READ_ONCE(dst_clu[i]); + + if (WARN_ON_ONCE(!new_clu)) + return; + + if (success) { + WRITE_ONCE(bat_entries[i], new_clu); + WRITE_ONCE(md->bat_levels[i], ploop_top_level(ploop)); + } else if (new_clu != READ_ONCE(bat_entries[i]) || + md->bat_levels[i] < ploop_top_level(ploop)) { + ploop_hole_set_bit(new_clu, ploop); + } +} + +static void ploop_advance_discarded(struct ploop *ploop, struct md_page *md, + map_index_t *dst_clu, u32 clu, bool success) +{ + u32 i = ploop_bat_clu_idx_in_page(clu); + u32 *bat_entries = md->kmpage; + u8 level = md->bat_levels[i]; + u32 d_clu = READ_ONCE(bat_entries[i]); + + if (!success || dst_clu[i] || d_clu == BAT_ENTRY_NONE || + level < ploop_top_level(ploop)) + return; + + WARN_ON_ONCE(ploop->nr_deltas != 1); + WRITE_ONCE(bat_entries[i], BAT_ENTRY_NONE); + WRITE_ONCE(md->bat_levels[i], 0); + ploop_hole_set_bit(d_clu, ploop); +} + /* - * Update local BAT copy with written indexes on success. - * Mark allocate clusters as holes on failure. + * Apply to the local BAT copy the changes made by the pios attached + * to @piwb, whatever type @piwb was prepared with: allocations and + * discards of one page may share a writeback. * FIXME: a failure may mean some sectors are written, so * we have to reread BAT page to check that. */ static void ploop_advance_local_after_bat_wb(struct ploop *ploop, struct ploop_index_wb *piwb, + struct llist_node *ll_ready_pios, + struct llist_node *ll_cow_pios, bool success) { struct md_page *md = piwb->md; - u32 i, last, *bat_entries; - map_index_t *dst_clu, off; + map_index_t *dst_clu; unsigned long flags; LIST_HEAD(list); struct llist_node *wait_llist_pending; + struct ploop_cow *cow; struct pio *pio; struct llist_node *pos, *t; BUG_ON(!md); - bat_entries = md->kmpage; - - /* Absolute number of first index in page (negative for page#0) */ - off = piwb->page_id * PAGE_SIZE / sizeof(map_index_t); - off -= PLOOP_MAP_OFFSET; spin_lock_irqsave(&ploop->bat_lock, flags); - /* Last and first index in copied page */ - last = READ_ONCE(ploop->nr_bat_entries) - off; - if (last > PAGE_SIZE / sizeof(map_index_t)) - last = PAGE_SIZE / sizeof(map_index_t); - i = 0; - if (!piwb->page_id) - i = PLOOP_MAP_OFFSET; - dst_clu = kmap_local_page(piwb->bat_page); /* holes bit map requires bat_lock */ spin_lock(&md->md_lock); - for (; i < last; i++) { - if (piwb->type == PIWB_TYPE_DISCARD) { - /* discard completed */ - u8 level = md->bat_levels[i]; - u32 d_clu = READ_ONCE(bat_entries[i]); - - if (success && !dst_clu[i] && - (!(d_clu == BAT_ENTRY_NONE || - level < ploop_top_level(ploop)))) { - WARN_ON_ONCE(ploop->nr_deltas != 1); - WRITE_ONCE(bat_entries[i], BAT_ENTRY_NONE); - WRITE_ONCE(md->bat_levels[i], 0); - ploop_hole_set_bit(d_clu, ploop); - } - - continue; - } - - if (!dst_clu[i]) - continue; - - if (success) { - WRITE_ONCE(bat_entries[i], READ_ONCE(dst_clu[i])); - WRITE_ONCE(md->bat_levels[i], ploop_top_level(ploop)); - } else if (dst_clu[i] != bat_entries[i] || - md->bat_levels[i] < ploop_top_level(ploop)) { - ploop_hole_set_bit(dst_clu[i], ploop); - } + llist_for_each(pos, ll_ready_pios) { + pio = list_entry((struct list_head *)pos, typeof(*pio), list); + if (pio->wants_discard_index_cleanup) + ploop_advance_discarded(ploop, md, dst_clu, pio->clu, success); + else if (pio->is_data_alloc) + ploop_advance_allocated(ploop, md, dst_clu, pio->clu, success); } + llist_for_each(pos, ll_cow_pios) { + pio = list_entry((struct list_head *)pos, typeof(*pio), list); + cow = pio->endio_cb_data; + ploop_advance_allocated(ploop, md, dst_clu, cow->cow_pio->clu, success); + } + if (piwb->reloc_clu != BAT_ENTRY_NONE) + ploop_advance_allocated(ploop, md, dst_clu, piwb->reloc_clu, success); WARN_ON_ONCE(!test_bit(MD_WRITEBACK, &md->status)); @@ -941,24 +954,6 @@ static void ploop_bat_write_finish(struct pio *pio, void *piwb_ptr, struct llist_node *ll_cow_pios; struct llist_node *ll_ready_pios; - if (!bi_status) { - /* - * Success: now update local BAT copy. We could do this - * from our delayed work, but we want to publish new - * mapping in the fastest way. This must be done before - * data bios completion, since right after we complete - * a bio, subsequent read wants to see written data - * (ploop_map() wants to see not zero bat_entries[.]). - */ - ploop_advance_local_after_bat_wb(ploop, piwb, true); - } else { - /* - * Index wb failed. Mark clusters as unallocated again. - * piwb->count is zero, so all data writers compeleted. - */ - ploop_advance_local_after_bat_wb(ploop, piwb, false); - } - spin_lock_irqsave(&piwb->lock, flags); ll_ready_pios = llist_del_all(&piwb->llready_data_pios); if (bi_status) @@ -966,6 +961,17 @@ static void ploop_bat_write_finish(struct pio *pio, void *piwb_ptr, spin_unlock_irqrestore(&piwb->lock, flags); ll_cow_pios = llist_reverse_order(llist_del_all(&piwb->cow_llist)); + /* + * On success publish the new mapping before the data bios + * complete, since right after we complete a bio, subsequent + * read wants to see written data (ploop_map() wants to see + * not zero bat_entries[.]). On failure mark the clusters + * allocated for this writeback as holes again: piwb->count + * is zero, so all data writers completed. + */ + ploop_advance_local_after_bat_wb(ploop, piwb, ll_ready_pios, + ll_cow_pios, !bi_status); + /* * End pending data bios. */ @@ -2708,6 +2714,7 @@ int ploop_prepare_reloc_index_wb(struct ploop *ploop, err = ploop_alloc_cluster(ploop, piwb, clu, dst_clu, file); if (err) goto out_reset; + piwb->reloc_clu = clu; } *ret_md = md; diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h index 23662943d56a..ce834df6df55 100644 --- a/drivers/md/dm-ploop.h +++ b/drivers/md/dm-ploop.h @@ -108,6 +108,7 @@ struct ploop_index_wb { blk_status_t bi_status; u32 page_id; struct bio_vec aux_bvec; + u32 reloc_clu; struct pio *flush_pio; }; -- 2.53.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel