[Devel] [PATCH rh7 1/2] cbt: new api: blk_cbt_map_merge()

Maxim Patlasov mpatlasov at virtuozzo.com
Tue May 24 17:50:10 PDT 2016


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 <mpatlasov at 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 14ad1a2..001dbfd 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -353,6 +353,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)
 {



More information about the Devel mailing list