This patch creates the testing module for nvm pages allocator. Before this module is loaded, the super block needs to be writen into nvdimm device (like /dev/pmemX). Signed-off-by: Jianpeng Ma <jianpeng.ma@xxxxxxxxx> Signed-off-by: Qiaowei Ren <qiaowei.ren@xxxxxxxxx> --- drivers/md/bcache/Kconfig | 6 ++ drivers/md/bcache/Makefile | 2 + drivers/md/bcache/test-nvm.c | 117 +++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 drivers/md/bcache/test-nvm.c diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig index 448a99ce13b2..1e4f4ea2f1a0 100644 --- a/drivers/md/bcache/Kconfig +++ b/drivers/md/bcache/Kconfig @@ -41,3 +41,9 @@ config BCACHE_NVM_PAGES depends on BCACHE help nvm pages allocator for bcache. + +config BCACHE_NVM_PAGES_TEST + tristate "Testing for NVM pages" + depends on BCACHE_NVM_PAGES + help + Testing module for NVM pages allocator. diff --git a/drivers/md/bcache/Makefile b/drivers/md/bcache/Makefile index 948e5ed2ca66..7b7d3535f4ef 100644 --- a/drivers/md/bcache/Makefile +++ b/drivers/md/bcache/Makefile @@ -5,3 +5,5 @@ obj-$(CONFIG_BCACHE) += bcache.o bcache-y := alloc.o bset.o btree.o closure.o debug.o extents.o\ io.o journal.o movinggc.o request.o stats.o super.o sysfs.o trace.o\ util.o writeback.o features.o nvm-pages.o + +obj-$(CONFIG_BCACHE_NVM_PAGES_TEST) += test-nvm.o diff --git a/drivers/md/bcache/test-nvm.c b/drivers/md/bcache/test-nvm.c new file mode 100644 index 000000000000..28133ceaa8fd --- /dev/null +++ b/drivers/md/bcache/test-nvm.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/crc32.h> +#include <linux/uuid.h> +#include <linux/prandom.h> +#include <linux/pagemap.h> +#include <linux/pfn_t.h> +#include "nvm-pages.h" + +static char *host = "NVDIMM device name"; +module_param(host, charp, 0444); + +#define MAX_OWNER 10 + +static pgoff_t vaddr_to_nvm_pgoff(struct nvm_namespace *ns, void *kaddr) +{ + return (kaddr - ns->kaddr - ns->pages_offset) / PAGE_SIZE; +} + +static void print_nvm_extent(struct nvm_alloced_recs *extents) +{ + struct list_head *list = extents->extent_head.next; + struct nvm_namespace *ns = extents->ns; + struct extent *e; + pgoff_t pgoff; + + while (list != &extents->extent_head) { + e = container_of(list, struct extent, list); + pgoff = vaddr_to_nvm_pgoff(ns, e->kaddr); + pr_info(" [%ld ~ %u)", pgoff, e->nr); + list = list->next; + } + pr_info("\n"); +} + +static void print_owner_list_info(struct nvm_set *nvm_set, bool print_extent) +{ + struct owner_list *owner_list; + struct nvm_alloced_recs *extents; + int i, j; + + for (i = 0; i < nvm_set->owner_list_size; i++) { + owner_list = nvm_set->owner_lists[i]; + pr_info("owner uuid=%pU\n", owner_list->owner_uuid); + for (j = 0; j < nvm_set->total_namespaces_nr; j++) { + if (owner_list->alloced_recs[j]) { + extents = owner_list->alloced_recs[j]; + pr_info("\t nvm uuid=%pU, allocated extents=%u\n", + extents->ns->uuid, extents->size); + if (print_extent) + print_nvm_extent(extents); + } + } + } +} + +static void test_case(struct nvm_set *nvm_set, char **owner_uuids) +{ + int i, order; + void *addr[MAX_OWNER]; + + for (i = 0; i < MAX_OWNER; i++) { + order = prandom_u32() % MAX_ORDER; + addr[i] = nvm_alloc_pages(order, owner_uuids[i]); + } + print_owner_list_info(nvm_set, true); + for (i = 0; i < MAX_OWNER; i++) { + struct page *page = virt_to_page(addr[i]); + + nvm_free_pages(addr[i], page->private, owner_uuids[i]); + } + print_owner_list_info(nvm_set, true); +} + +static int __init test_nvm_init(void) +{ + char **owner_uuids; + struct nvm_set *nvm_set; + int i, r = 0; + struct nvm_namespace *ns = register_namespace(host); + + pr_info("nvm pages test enter: %s\n", host); + if (IS_ERR(ns)) { + pr_info("failed to register namespace: %s\n", host); + r = -EINVAL; + goto err; + } + + owner_uuids = kcalloc(MAX_OWNER, sizeof(char *), GFP_KERNEL); + for (i = 0; i < MAX_OWNER; i++) { + owner_uuids[i] = kmalloc(16, GFP_KERNEL); + generate_random_uuid(owner_uuids[i]); + } + + nvm_set = ns->nvm_set; + test_case(nvm_set, owner_uuids); + + for (i = 0; i < MAX_OWNER; i++) + kfree(owner_uuids[i]); + kfree(owner_uuids); + +err: + return r; +} +module_init(test_nvm_init); + +static void __exit test_nvm_exit(void) +{ + pr_info("nvm pages test exit\n"); +} +module_exit(test_nvm_exit); + +MODULE_LICENSE("GPL v2"); -- 2.17.1