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 <[email protected]> --- 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 b9be80492eae..8e696ac2fcf4 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) _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
