[Devel] [PATCH rh7 5/5] cbt: add blk_cbt_map_copy_once() helper
Maxim Patlasov
mpatlasov at virtuozzo.com
Fri Apr 8 18:51:13 PDT 2016
Ploop will use the helper to make private "snapshot" copy of CBT mask.
Signed-off-by: Maxim Patlasov <mpatlasov 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