The commit is pushed to "branch-rh7-3.10.0-327.18.2.vz7.14.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.18.2.vz7.14.8
------>
commit 9593dfbcdf328c1c9fe5e1f5cb8c11ccef7ddf08
Author: Maxim Patlasov <mpatla...@virtuozzo.com>
Date:   Fri May 27 13:15:20 2016 +0400

    cbt: new api: blk_cbt_map_merge()
    
    Patchset description:
    ploop: push_backup: preserve CBT mask
    
    The first patch of the set implements a helper to merge a copy of
    CBT mask back to CBT: blk_cbt_map_merge().
    
    The second patch implements the following logic: keep a copy of
    CBT mask until either userspace reports success/failure of
    push_backup or ploop is released ultimately.
    
    If user reports success, free the copy. In all other cases,
    the copy is merged back to CBT. This will allow re-do
    push_backup if backup tool crashes in the middle.
    
    https://jira.sw.ru/browse/PSBM-47429
    
    Maxim Patlasov (2):
          cbt: new api: blk_cbt_map_merge()
          ploop: push_backup: merge pbd->cbt_map back to CBT
    
    ========================================
    This patch description:
    
    New api blk_cbt_map_copy_once() allows to merge a copy -- acquired earlier 
by
    blk_cbt_map_copy_once() -- back to main CBT mask. This is useful to handle
    userspace backup tool crashes.
    
    https://jira.sw.ru/browse/PSBM-47429
    
    Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
---
 block/blk-cbt.c        | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/blkdev.h |  3 +++
 2 files changed, 70 insertions(+)

diff --git a/block/blk-cbt.c b/block/blk-cbt.c
index 8ba52fb..d635186 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -348,6 +348,73 @@ fail:
 }
 EXPORT_SYMBOL(blk_cbt_map_copy_once);
 
+static void blk_cbt_page_merge(struct page *pg_from, struct page *pg_to)
+{
+       u32 *from = page_address(pg_from);
+       u32 *to = page_address(pg_to);
+       u32 *fin = to + PAGE_SIZE/sizeof(*to);
+
+       while (to < fin) {
+               *to |= *from;
+               to++;
+               from++;
+       }
+}
+
+int blk_cbt_map_merge(struct request_queue *q, __u8 *uuid,
+                     struct page **map, blkcnt_t block_max,
+                     blkcnt_t block_bits)
+{
+       struct cbt_info *cbt;
+       unsigned long i;
+
+       mutex_lock(&cbt_mutex);
+       cbt = q->cbt;
+
+       if (!cbt) {
+               mutex_unlock(&cbt_mutex);
+               return -ENOENT;
+       }
+
+       BUG_ON(!cbt->map);
+       BUG_ON(!cbt->block_max);
+
+       if (!map || !uuid || memcmp(uuid, cbt->uuid, sizeof(cbt->uuid)) ||
+           block_max != cbt->block_max || block_bits != cbt->block_bits) {
+               mutex_unlock(&cbt_mutex);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < NR_PAGES(cbt->block_max); i++) {
+               struct page *page_main = cbt->map[i];
+               struct page *page_addon = map[i];
+
+               BUG_ON(page_main == CBT_PAGE_MISSED);
+               BUG_ON(page_addon == CBT_PAGE_MISSED);
+
+               if (!page_addon)
+                       continue;
+
+               if (!page_main) {
+                       int ret = cbt_page_alloc(&cbt, i, 0);
+                       if (ret) {
+                               mutex_unlock(&cbt_mutex);
+                               return ret;
+                       }
+                       page_main = cbt->map[i];
+                       BUG_ON(page_main == NULL);
+                       BUG_ON(page_main == CBT_PAGE_MISSED);
+               }
+
+               spin_lock_page(page_main);
+               blk_cbt_page_merge(page_addon, page_main);
+               unlock_page(page_main);
+       }
+       mutex_unlock(&cbt_mutex);
+       return 0;
+}
+EXPORT_SYMBOL(blk_cbt_map_merge);
+
 void blk_cbt_update_size(struct block_device *bdev)
 {
        struct request_queue *q;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 56c3a08..c16f4da 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1654,6 +1654,9 @@ extern int blk_cbt_ioctl(struct block_device *bdev, 
unsigned cmd, char __user *a
 extern int blk_cbt_map_copy_once(struct request_queue *q, __u8 *uuid,
                                 struct page ***map_ptr, blkcnt_t *block_max,
                                 blkcnt_t *block_bits);
+extern int blk_cbt_map_merge(struct request_queue *q, __u8 *uuid,
+                            struct page **map, blkcnt_t block_max,
+                            blkcnt_t block_bits);
 #else /* CONFIG_BLK_DEV_CBT */
 static inline void blk_cbt_update_size(struct block_device *bdev)
 {
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to