We mustn't have obsolete data in cached pages.
In this BUG this resulted in that next update
of page 0 metadata overwrites header on disk
with old value.

https://jira.sw.ru/browse/PSBM-129136

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

diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index 0b8ef1382717..f259ff5d7652 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -313,6 +313,8 @@ static int ploop_grow_update_header(struct ploop *ploop,
 {
        unsigned int size, first_block_off, cluster_log = ploop->cluster_log;
        struct ploop_pvd_header *hdr;
+       u32 nr_be, offset;
+       u64 sectors;
        int ret;
 
        /* hdr is in the same page as bat_entries[0] index */
@@ -327,13 +329,21 @@ static int ploop_grow_update_header(struct ploop *ploop,
 
        hdr = kmap_atomic(piwb->bat_page);
        /* TODO: head and cylinders */
-       hdr->m_Size = cpu_to_le32(cmd->resize.nr_bat_entries);
-       hdr->m_SizeInSectors_v2 = cpu_to_le64(cmd->resize.new_size);
-       hdr->m_FirstBlockOffset = cpu_to_le32(first_block_off);
+       nr_be = hdr->m_Size = cpu_to_le32(cmd->resize.nr_bat_entries);
+       sectors = hdr->m_SizeInSectors_v2 = cpu_to_le64(cmd->resize.new_size);
+       offset = hdr->m_FirstBlockOffset = cpu_to_le32(first_block_off);
        kunmap_atomic(hdr);
 
        ploop_submit_index_wb_sync(ploop, piwb);
        ret = blk_status_to_errno(piwb->bi_status);
+       if (!ret) {
+               /* Now update our cached page */
+               hdr = kmap_atomic(cmd->resize.md0->page);
+               hdr->m_Size = nr_be;
+               hdr->m_SizeInSectors_v2 = sectors;
+               hdr->m_FirstBlockOffset = offset;
+               kunmap_atomic(hdr);
+       }
 
        ploop_reset_bat_update(piwb);
        return ret;
@@ -463,7 +473,7 @@ static int ploop_resize(struct ploop *ploop, u64 new_size)
        unsigned int hb_nr, size, cluster_log = ploop->cluster_log;
        struct ploop_cmd cmd = { .resize.md_pages_root = RB_ROOT };
        struct ploop_pvd_header *hdr;
-       struct md_page *md;
+       struct md_page *md0;
        int ret = -ENOMEM;
        u64 old_size;
 
@@ -472,12 +482,12 @@ static int ploop_resize(struct ploop *ploop, u64 new_size)
        if (ploop_is_ro(ploop))
                return -EROFS;
 
-       md = md_page_find(ploop, 0);
-       if (WARN_ON(!md))
+       md0 = md_page_find(ploop, 0);
+       if (WARN_ON(!md0))
                return -EIO;
-       hdr = kmap(md->page);
+       hdr = kmap(md0->page);
        old_size = le64_to_cpu(hdr->m_SizeInSectors_v2);
-       kunmap(md->page);
+       kunmap(md0->page);
 
        if (old_size == new_size)
                return 0;
@@ -528,6 +538,7 @@ static int ploop_resize(struct ploop *ploop, u64 new_size)
        cmd.resize.nr_bat_entries = nr_bat_entries;
        cmd.resize.hb_nr = hb_nr;
        cmd.resize.new_size = new_size;
+       cmd.resize.md0 = md0;
        cmd.retval = 0;
        cmd.type = PLOOP_CMD_RESIZE;
        cmd.ploop = ploop;
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index e2af133c45a2..466f1506741e 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -57,6 +57,7 @@ struct ploop_cmd {
                        u64 new_size;
                        /* Preallocated data */
                        struct rb_root md_pages_root;
+                       struct md_page *md0;
                        void *holes_bitmap;
 #define PLOOP_GROW_STAGE_INITIAL       0
                        unsigned int stage;


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

Reply via email to