Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com>
---
 drivers/md/dm-ploop-bat.c |   30 +++++++++++++++++++++---------
 drivers/md/dm-ploop.h     |    1 +
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/md/dm-ploop-bat.c b/drivers/md/dm-ploop-bat.c
index 45f651ce5549..c17f874fc25d 100644
--- a/drivers/md/dm-ploop-bat.c
+++ b/drivers/md/dm-ploop-bat.c
@@ -420,7 +420,7 @@ static void apply_delta_mappings(struct ploop *ploop, 
struct ploop_delta *deltas
                                 u32 level, void *hdr, u64 size_in_clus)
 {
        map_index_t *bat_entries, *delta_bat_entries;
-       unsigned int i, end, dst_cluster;
+       unsigned int i, end, dst_cluster, clu;
        struct rb_node *node;
        struct md_page *md;
        bool is_raw;
@@ -434,13 +434,16 @@ static void apply_delta_mappings(struct ploop *ploop, 
struct ploop_delta *deltas
                init_bat_entries_iter(ploop, md->id, &i, &end);
                bat_entries = kmap_atomic(md->page);
                for (; i <= end; i++) {
+                       clu = page_clu_idx_to_bat_clu(md->id, i);
+                       if (clu >= size_in_clus)
+                               goto unlock;
                        if (bat_entries[i] != BAT_ENTRY_NONE)
                                continue;
 
                        if (!is_raw)
                                dst_cluster = delta_bat_entries[i];
                        else {
-                               dst_cluster = page_clu_idx_to_bat_clu(md->id, 
i);
+                               dst_cluster = clu;
                                if (dst_cluster >= size_in_clus)
                                        dst_cluster = BAT_ENTRY_NONE;
                        }
@@ -453,11 +456,12 @@ static void apply_delta_mappings(struct ploop *ploop, 
struct ploop_delta *deltas
                kunmap_atomic(bat_entries);
                delta_bat_entries += PAGE_SIZE / sizeof(map_index_t);
        }
+unlock:
        write_unlock_irq(&ploop->bat_rwlock);
 }
 
 static int ploop_check_delta_length(struct ploop *ploop, struct file *file,
-                                   u64 *size_in_clus)
+                                   u32 *size_in_clus)
 {
        loff_t loff = i_size_read(file->f_mapping->host);
        unsigned int cluster_log = ploop->cluster_log;
@@ -475,9 +479,9 @@ static int ploop_check_delta_length(struct ploop *ploop, 
struct file *file,
 int ploop_add_delta(struct ploop *ploop, u32 level, int fd, bool is_raw)
 {
        struct ploop_delta *deltas = ploop->deltas;
+       struct ploop_pvd_header *hdr = NULL;
        struct file *file;
-       u64 size_in_clus;
-       void *hdr = NULL;
+       u32 size_in_clus;
        int ret;
 
        file = fget(fd);
@@ -491,14 +495,22 @@ int ploop_add_delta(struct ploop *ploop, u32 level, int 
fd, bool is_raw)
        if (ret)
                goto out;
 
-       if (!is_raw)
-               ret = ploop_read_delta_metadata(ploop, file, &hdr);
-       if (ret)
+       if (!is_raw) {
+               ret = ploop_read_delta_metadata(ploop, file, (void *)&hdr);
+               if (ret)
+                       goto out;
+               size_in_clus = le32_to_cpu(hdr->m_Size);
+       }
+
+       ret = -EBADSLT;
+       if (level != ploop->nr_deltas - 1 &&
+           size_in_clus > deltas[level + 1].size_in_clus)
                goto out;
 
-       apply_delta_mappings(ploop, deltas, level, hdr, size_in_clus);
+       apply_delta_mappings(ploop, deltas, level, (void *)hdr, size_in_clus);
 
        deltas[level].file = file;
+       deltas[level].size_in_clus = size_in_clus;
        deltas[level].is_raw = is_raw;
        ret = 0;
 out:
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 1eeac9ca064d..e21a0ab83378 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -34,6 +34,7 @@ struct ploop_pvd_header {
 
 struct ploop_delta {
        struct file *file;
+       u32 size_in_clus;
        bool is_raw;
 };
 


_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to