[Devel] [PATCH RHEL8 COMMIT] dm-ploop: Fix middle delta merges
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Aug 13 15:41:25 MSK 2021
The commit is pushed to "branch-rh8-4.18.0-305.3.1.vz8.7.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-305.3.1.vz8.7.6
------>
commit f4c9b26a75c5c7793e44405ea8af279aa109e53c
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date: Fri Aug 13 15:41:25 2021 +0300
dm-ploop: Fix middle delta merges
This makes images size to update after delta metadata re-read
and also fixes algorithm of bat_entries[] assignment.
https://jira.sw.ru/browse/PSBM-132561
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
drivers/md/dm-ploop-cmd.c | 47 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index 41c3996e6b38..e313619c95e3 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -709,28 +709,33 @@ static void notify_delta_merged(struct ploop *ploop, u8 level,
if (clu == size_in_clus - 1)
stop = true;
- if (md_page_cluster_is_in_top_delta(ploop, md, i) ||
- d_bat_entries[i] == BAT_ENTRY_NONE ||
- md->bat_levels[i] < level)
- continue;
-
/* deltas above @level become renumbered */
- if (md->bat_levels[i] > level) {
+ if (bat_entries[i] != BAT_ENTRY_NONE &&
+ md->bat_levels[i] > level) {
md->bat_levels[i]--;
continue;
}
+ if (bat_entries[i] != BAT_ENTRY_NONE &&
+ md->bat_levels[i] < level)
+ continue;
+
+ if (d_bat_entries[i] == BAT_ENTRY_NONE) {
+ WARN_ON_ONCE(bat_entries[i] != BAT_ENTRY_NONE);
+ continue;
+ }
+
/*
* clusters from deltas of @level become pointing to
* 1)next delta (which became renumbered) or
* 2)prev delta (if !@forward).
*/
bat_entries[i] = d_bat_entries[i];
- WARN_ON(bat_entries[i] == BAT_ENTRY_NONE);
if (!forward)
- md->bat_levels[i]--;
+ md->bat_levels[i] = level - 1;
+ else
+ md->bat_levels[i] = level;
}
-
kunmap_atomic(bat_entries);
kunmap_atomic(d_bat_entries);
if (stop)
@@ -742,7 +747,8 @@ static void notify_delta_merged(struct ploop *ploop, u8 level,
/* Renumber deltas above @level */
for (i = level + 1; i < ploop->nr_deltas; i++)
ploop->deltas[i - 1] = ploop->deltas[i];
- ploop->deltas[--ploop->nr_deltas].file = NULL;
+ memset(&ploop->deltas[--ploop->nr_deltas], 0,
+ sizeof(struct ploop_delta));
write_unlock_irq(&ploop->bat_rwlock);
fput(file);
}
@@ -780,24 +786,41 @@ static int process_update_delta_index(struct ploop *ploop, u8 level,
static int ploop_delta_clusters_merged(struct ploop *ploop, u8 level,
bool forward)
{
+ struct ploop_delta *deltas = ploop->deltas;
struct rb_root md_root = RB_ROOT;
struct file *file;
+ loff_t file_size;
u32 size_in_clus;
+ u8 changed_level;
int ret;
/* Reread BAT of deltas[@level + 1] (or [@level - 1]) */
- file = ploop->deltas[level + forward ? 1 : -1].file;
+ changed_level = level + (forward ? 1 : -1);
+ file = deltas[changed_level].file;
+
+ ret = ploop_check_delta_length(ploop, file, &file_size);
+ if (ret)
+ goto out;
ret = ploop_read_delta_metadata(ploop, file, &md_root, &size_in_clus);
if (ret)
goto out;
+ ret = -EFBIG;
+ if (changed_level != top_level(ploop) &&
+ size_in_clus > deltas[changed_level + 1].size_in_clus)
+ goto out;
+
ret = ploop_suspend_submitting_pios(ploop);
if (ret)
goto out;
notify_delta_merged(ploop, level, &md_root, forward, size_in_clus);
+ deltas[changed_level].file_size = file_size;
+ deltas[changed_level].file_preallocated_area_start = file_size;
+ deltas[changed_level].size_in_clus = size_in_clus;
+
ploop_resume_submitting_pios(ploop);
ret = 0;
out:
@@ -813,6 +836,8 @@ static int ploop_notify_merged(struct ploop *ploop, u8 level, bool forward)
return -ENOENT;
if (level == 0 && !forward)
return -EINVAL;
+ if (level == 0 && ploop->deltas[0].is_raw)
+ return -ENOTSUPP;
if (level == top_level(ploop) - 1 && forward)
return -EINVAL;
if (ploop->nr_deltas < 3)
More information about the Devel
mailing list