[Devel] [PATCH hci-8.1 v2 2/4] dm-ploop: renumber BAT levels when the latest snapshot is merged

Denis V. Lunev den at openvz.org
Wed Oct 28 17:36:45 MSK 2026


From: Denis V. Lunev <den at openvz.org>

ploop_merge_latest_snapshot() drops the delta below the top one and
moves the top delta down a level, but leaves bat_levels alone. Every
cluster of the top delta then sits one level above the new top.

Checks done with "< top" do not notice, but the flip of the upper
deltas compares levels for equality and leaves these entries alone.
After the flip they are still taken for the top delta, so their I/O
goes to the delta that has just become the top one, at offsets that
belong to the other file. An ALLOC or RELOC writeback resets the
level of every entry it writes back, which hid this for the pages
that happened to get one.

Lower the levels above the dropped delta and clear the slot the top
delta moved out of, as notify_delta_merged() does for a delta merged
from userspace.

Fixes: 6ddad5a4d226 ("dm-ploop: Add ploop target driver")
https://virtuozzo.atlassian.net/browse/VSTOR-151979

Signed-off-by: Denis V. Lunev <den at openvz.org>
Reviewed-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>

Feature: dm-ploop: ploop target driver
---
 drivers/md/dm-ploop-cmd.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index 5fa78e6cff9a..b3d96bb657ed 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -721,6 +721,27 @@ static int ploop_process_merge_latest_snapshot(struct ploop *ploop)
 }
 ALLOW_ERROR_INJECTION(ploop_process_merge_latest_snapshot, ERRNO);
 
+static void ploop_renumber_levels_above(struct ploop *ploop, u8 level)
+{
+	u32 i, end, *bat_entries;
+	struct md_page *md;
+	struct rb_node *node;
+	unsigned long flags;
+
+	ploop_for_each_md_page(ploop, md, node) {
+		ploop_init_be_iter(ploop, md->id, &i, &end);
+		bat_entries = md->kmpage;
+
+		spin_lock_irqsave(&md->md_lock, flags); /* write */
+		for (; i <= end; i++) {
+			if (READ_ONCE(bat_entries[i]) != BAT_ENTRY_NONE &&
+			    READ_ONCE(md->bat_levels[i]) > level)
+				md->bat_levels[i]--;
+		}
+		spin_unlock_irqrestore(&md->md_lock, flags);
+	}
+}
+
 static int ploop_merge_latest_snapshot(struct ploop *ploop)
 {
 	u8 level;
@@ -747,7 +768,9 @@ static int ploop_merge_latest_snapshot(struct ploop *ploop)
 	ploop_put_delta(ploop, &ploop->deltas[level]);
 
 	ploop->deltas[level] = ploop->deltas[level + 1];
-	ploop->nr_deltas--;
+	memset(&ploop->deltas[--ploop->nr_deltas], 0,
+	       sizeof(struct ploop_delta));
+	ploop_renumber_levels_above(ploop, level);
 
 	ploop_resume_submitting_pios(ploop);
 out:
-- 
2.53.0



More information about the Devel mailing list