[Devel] [PATCH RHEL7 COMMIT] cbt: add blk_cbt_map_copy_once() helper

Konstantin Khorenko khorenko at virtuozzo.com
Tue Apr 12 03:24:17 PDT 2016


The commit is pushed to "branch-rh7-3.10.0-327.10.1.vz7.12.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.10.1.vz7.12.7
------>
commit 338748c5c8ef8c4e9cf297c504ae2f60b213b352
Author: Maxim Patlasov <mpatlasov at virtuozzo.com>
Date:   Tue Apr 12 14:24:16 2016 +0400

    cbt: add blk_cbt_map_copy_once() helper
    
    Ploop will use the helper to make private "snapshot" copy of CBT mask.
    
    https://jira.sw.ru/browse/PSBM-45000
    
    Signed-off-by: Maxim Patlasov <mpatlasov at virtuozzo.com>
    Acked-by: Dmitry Monakhov <dmonakhov at virtuozzo.com>
---
 block/blk-cbt.c        | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/blkdev.h |  2 ++
 2 files changed, 61 insertions(+)

diff --git a/block/blk-cbt.c b/block/blk-cbt.c
index 4bf9666..850fd7e 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -278,6 +278,65 @@ err_cbt:
 	return ERR_PTR(-ENOMEM);
 }
 
+int blk_cbt_map_copy_once(struct request_queue *q, struct page ***map_ptr,
+			  blkcnt_t *block_max, blkcnt_t *block_bits)
+{
+	struct cbt_info *cbt;
+	struct page **map;
+	unsigned long npages;
+	unsigned long i;
+
+	mutex_lock(&cbt_mutex);
+	cbt = q->cbt;
+
+	BUG_ON(!cbt);
+	BUG_ON(!cbt->map);
+	BUG_ON(!cbt->block_max);
+
+	cbt_flush_cache(cbt);
+
+	npages = NR_PAGES(cbt->block_max);
+	map = vmalloc(npages * sizeof(void*));
+	if (!map)
+		goto fail;
+
+	memset(map, 0, npages * sizeof(void*));
+
+	for (i = 0; i < npages; i++) {
+		struct page *page = cbt->map[i];
+
+		BUG_ON(page == CBT_PAGE_MISSED);
+
+		if (page) {
+			map[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
+			if (!map[i])
+				goto fail_pages;
+
+			spin_lock_page(page);
+			memcpy(page_address(map[i]), page_address(page),
+			       PAGE_SIZE);
+			memset(page_address(page), 0, PAGE_SIZE);
+			unlock_page(page);
+		}
+	}
+	mutex_unlock(&cbt_mutex);
+
+	*map_ptr = map;
+	*block_max = cbt->block_max;
+	*block_bits = cbt->block_bits;
+	return 0;
+
+fail_pages:
+	while (--i >= 0) {
+		if (map[i])
+			__free_page(map[i]);
+	}
+fail:
+	vfree(map);
+	mutex_unlock(&cbt_mutex);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(blk_cbt_map_copy_once);
 
 void blk_cbt_update_size(struct block_device *bdev)
 {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 9dc69cb..7ae962a 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1651,6 +1651,8 @@ extern void blk_cbt_update_size(struct block_device *bdev);
 extern void blk_cbt_release(struct request_queue *q);
 extern void blk_cbt_bio_queue(struct request_queue *q, struct bio *bio);
 extern int blk_cbt_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg);
+extern int blk_cbt_map_copy_once(struct request_queue *q, struct page ***map_ptr,
+				 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