[Devel] [PATCH hci-8.1 v2 2/3] dm-ploop: refuse flip_upper_deltas onto a lower delta smaller than the device
Denis V. Lunev
den at openvz.org
Thu Nov 5 17:57:48 MSK 2026
From: Denis V. Lunev <den at openvz.org>
A flip_upper_deltas after a grow of the device, with the lower delta
left at its old size, makes a top delta whose header and BAT cover fewer
entries than the device. After resume the BAT writeback puts the grown
header into page 0 of that file and the BAT pages past its old size onto
its data clusters, and the image no longer opens.
Today ploop_check_delta_before_flip() oopses on such a flip before it
gets that far, as its walk runs past the end of the BAT of the lower
delta. Fixing the walk alone would let the flip through.
Read the header of the lower delta on every flip, not only under
PLOOP_DEBUG, and refuse with -EBADSLT when it has fewer BAT entries than
the device, as ploop_add_delta() refuses a lower delta bigger than the
upper one. Compare entries, not BAT pages: fewer entries in the same
number of pages still gives a stack that ploop_add_delta() refuses on
the next load. The reverse merge of the ploop library grows the lower
delta to the size of the device before it flips, so it never gets the
refusal.
Fixes: 6ddad5a4d226 ("dm-ploop: Add ploop target driver")
https://virtuozzo.atlassian.net/browse/VSTOR-153445
Feature: dm-ploop: ploop target driver
Signed-off-by: Denis V. Lunev <den at openvz.org>
---
drivers/md/dm-ploop-cmd.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index d6abbdc3c7e3..5549ba448594 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -1118,20 +1118,27 @@ static int ploop_set_noresume(struct ploop *ploop, char *mode)
static int ploop_check_delta_before_flip(struct ploop *ploop, struct file *file)
{
- int ret = 0;
-#ifdef PLOOP_DEBUG
- u32 i, end, *d_bat_entries, clu, nr_be;
struct rb_root md_root = RB_ROOT;
+ u32 nr_be;
+ int ret;
+#ifdef PLOOP_DEBUG
+ u32 i, end, *d_bat_entries, clu;
struct md_page *md, *d_md;
struct rb_node *node;
bool stop = false;
+#endif
ret = ploop_read_delta_metadata(ploop, file, &md_root, &nr_be);
if (ret) {
PL_ERR("Error reading metadata");
- goto out;
+ return ret;
}
+ ret = -EBADSLT;
+ if (nr_be < ploop->nr_bat_entries)
+ goto free;
+ ret = 0;
+#ifdef PLOOP_DEBUG
/* Points to hdr since md_page[0] also contains hdr. */
d_md = ploop_md_first_entry(&md_root);
@@ -1164,10 +1171,9 @@ static int ploop_check_delta_before_flip(struct ploop *ploop, struct file *file)
break;
d_md = ploop_md_next_entry(d_md);
}
-
- ploop_free_md_pages_tree(&md_root);
-out:
#endif
+free:
+ ploop_free_md_pages_tree(&md_root);
return ret;
}
--
2.53.0
More information about the Devel
mailing list