Skip to content

Commit b2b7e00

Browse files
MatiasBjorlingaxboe
authored andcommitted
null_blk: register as a LightNVM device
Add support for registering as a LightNVM device. This allows us to evaluate the performance of the LightNVM subsystem. In /drivers/Makefile, LightNVM is moved above block device drivers to make sure that the LightNVM media managers have been initialized before drivers under /drivers/block are initialized. Signed-off-by: Matias Bjørling <m@bjorling.me> Fix by Jens Axboe to remove unneeded slab cache and the following memory leak. Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent 4736346 commit b2b7e00

File tree

3 files changed

+158
-7
lines changed

3 files changed

+158
-7
lines changed

Documentation/block/null_blk.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ use_per_node_hctx=[0/1]: Default: 0
7070
parameter.
7171
1: The multi-queue block layer is instantiated with a hardware dispatch
7272
queue for each CPU node in the system.
73+
74+
use_lightnvm=[0/1]: Default: 0
75+
Register device with LightNVM. Requires blk-mq to be used.

drivers/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ obj-$(CONFIG_FB_I810) += video/fbdev/i810/
6363
obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/
6464

6565
obj-$(CONFIG_PARPORT) += parport/
66+
obj-$(CONFIG_NVM) += lightnvm/
6667
obj-y += base/ block/ misc/ mfd/ nfc/
6768
obj-$(CONFIG_LIBNVDIMM) += nvdimm/
6869
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
6970
obj-$(CONFIG_NUBUS) += nubus/
7071
obj-y += macintosh/
7172
obj-$(CONFIG_IDE) += ide/
7273
obj-$(CONFIG_SCSI) += scsi/
73-
obj-$(CONFIG_NVM) += lightnvm/
7474
obj-y += nvme/
7575
obj-$(CONFIG_ATA) += ata/
7676
obj-$(CONFIG_TARGET_CORE) += target/

drivers/block/null_blk.c

Lines changed: 154 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/slab.h>
99
#include <linux/blk-mq.h>
1010
#include <linux/hrtimer.h>
11+
#include <linux/lightnvm.h>
1112

1213
struct nullb_cmd {
1314
struct list_head list;
@@ -39,6 +40,7 @@ struct nullb {
3940

4041
struct nullb_queue *queues;
4142
unsigned int nr_queues;
43+
char disk_name[DISK_NAME_LEN];
4244
};
4345

4446
static LIST_HEAD(nullb_list);
@@ -119,6 +121,10 @@ static int nr_devices = 2;
119121
module_param(nr_devices, int, S_IRUGO);
120122
MODULE_PARM_DESC(nr_devices, "Number of devices to register");
121123

124+
static bool use_lightnvm;
125+
module_param(use_lightnvm, bool, S_IRUGO);
126+
MODULE_PARM_DESC(use_lightnvm, "Register as a LightNVM device");
127+
122128
static int irqmode = NULL_IRQ_SOFTIRQ;
123129

124130
static int null_set_irqmode(const char *str, const struct kernel_param *kp)
@@ -427,6 +433,8 @@ static void null_del_dev(struct nullb *nullb)
427433
{
428434
list_del_init(&nullb->list);
429435

436+
if (use_lightnvm)
437+
nvm_unregister(nullb->disk->disk_name);
430438
del_gendisk(nullb->disk);
431439
blk_cleanup_queue(nullb->q);
432440
if (queue_mode == NULL_Q_MQ)
@@ -436,6 +444,125 @@ static void null_del_dev(struct nullb *nullb)
436444
kfree(nullb);
437445
}
438446

447+
#ifdef CONFIG_NVM
448+
449+
static void null_lnvm_end_io(struct request *rq, int error)
450+
{
451+
struct nvm_rq *rqd = rq->end_io_data;
452+
struct nvm_dev *dev = rqd->dev;
453+
454+
dev->mt->end_io(rqd, error);
455+
456+
blk_put_request(rq);
457+
}
458+
459+
static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
460+
{
461+
struct request *rq;
462+
struct bio *bio = rqd->bio;
463+
464+
rq = blk_mq_alloc_request(q, bio_rw(bio), GFP_KERNEL, 0);
465+
if (IS_ERR(rq))
466+
return -ENOMEM;
467+
468+
rq->cmd_type = REQ_TYPE_DRV_PRIV;
469+
rq->__sector = bio->bi_iter.bi_sector;
470+
rq->ioprio = bio_prio(bio);
471+
472+
if (bio_has_data(bio))
473+
rq->nr_phys_segments = bio_phys_segments(q, bio);
474+
475+
rq->__data_len = bio->bi_iter.bi_size;
476+
rq->bio = rq->biotail = bio;
477+
478+
rq->end_io_data = rqd;
479+
480+
blk_execute_rq_nowait(q, NULL, rq, 0, null_lnvm_end_io);
481+
482+
return 0;
483+
}
484+
485+
static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
486+
{
487+
sector_t size = gb * 1024 * 1024 * 1024ULL;
488+
struct nvm_id_group *grp;
489+
490+
id->ver_id = 0x1;
491+
id->vmnt = 0;
492+
id->cgrps = 1;
493+
id->cap = 0x3;
494+
id->dom = 0x1;
495+
id->ppat = NVM_ADDRMODE_LINEAR;
496+
497+
do_div(size, bs); /* convert size to pages */
498+
grp = &id->groups[0];
499+
grp->mtype = 0;
500+
grp->fmtype = 1;
501+
grp->num_ch = 1;
502+
grp->num_lun = 1;
503+
grp->num_pln = 1;
504+
grp->num_blk = size / 256;
505+
grp->num_pg = 256;
506+
grp->fpg_sz = bs;
507+
grp->csecs = bs;
508+
grp->trdt = 25000;
509+
grp->trdm = 25000;
510+
grp->tprt = 500000;
511+
grp->tprm = 500000;
512+
grp->tbet = 1500000;
513+
grp->tbem = 1500000;
514+
grp->mpos = 0x010101; /* single plane rwe */
515+
grp->cpar = hw_queue_depth;
516+
517+
return 0;
518+
}
519+
520+
static void *null_lnvm_create_dma_pool(struct request_queue *q, char *name)
521+
{
522+
mempool_t *virtmem_pool;
523+
524+
virtmem_pool = mempool_create_page_pool(64, 0);
525+
if (!virtmem_pool) {
526+
pr_err("null_blk: Unable to create virtual memory pool\n");
527+
return NULL;
528+
}
529+
530+
return virtmem_pool;
531+
}
532+
533+
static void null_lnvm_destroy_dma_pool(void *pool)
534+
{
535+
mempool_destroy(pool);
536+
}
537+
538+
static void *null_lnvm_dev_dma_alloc(struct request_queue *q, void *pool,
539+
gfp_t mem_flags, dma_addr_t *dma_handler)
540+
{
541+
return mempool_alloc(pool, mem_flags);
542+
}
543+
544+
static void null_lnvm_dev_dma_free(void *pool, void *entry,
545+
dma_addr_t dma_handler)
546+
{
547+
mempool_free(entry, pool);
548+
}
549+
550+
static struct nvm_dev_ops null_lnvm_dev_ops = {
551+
.identity = null_lnvm_id,
552+
.submit_io = null_lnvm_submit_io,
553+
554+
.create_dma_pool = null_lnvm_create_dma_pool,
555+
.destroy_dma_pool = null_lnvm_destroy_dma_pool,
556+
.dev_dma_alloc = null_lnvm_dev_dma_alloc,
557+
.dev_dma_free = null_lnvm_dev_dma_free,
558+
559+
/* Simulate nvme protocol restriction */
560+
.max_phys_sect = 64,
561+
};
562+
#else
563+
static struct nvm_dev_ops null_lnvm_dev_ops;
564+
#endif /* CONFIG_NVM */
565+
439566
static int null_open(struct block_device *bdev, fmode_t mode)
440567
{
441568
return 0;
@@ -575,11 +702,6 @@ static int null_add_dev(void)
575702
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q);
576703
queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nullb->q);
577704

578-
disk = nullb->disk = alloc_disk_node(1, home_node);
579-
if (!disk) {
580-
rv = -ENOMEM;
581-
goto out_cleanup_blk_queue;
582-
}
583705

584706
mutex_lock(&lock);
585707
list_add_tail(&nullb->list, &nullb_list);
@@ -589,6 +711,21 @@ static int null_add_dev(void)
589711
blk_queue_logical_block_size(nullb->q, bs);
590712
blk_queue_physical_block_size(nullb->q, bs);
591713

714+
sprintf(nullb->disk_name, "nullb%d", nullb->index);
715+
716+
if (use_lightnvm) {
717+
rv = nvm_register(nullb->q, nullb->disk_name,
718+
&null_lnvm_dev_ops);
719+
if (rv)
720+
goto out_cleanup_blk_queue;
721+
goto done;
722+
}
723+
724+
disk = nullb->disk = alloc_disk_node(1, home_node);
725+
if (!disk) {
726+
rv = -ENOMEM;
727+
goto out_cleanup_lightnvm;
728+
}
592729
size = gb * 1024 * 1024 * 1024ULL;
593730
set_capacity(disk, size >> 9);
594731

@@ -598,10 +735,15 @@ static int null_add_dev(void)
598735
disk->fops = &null_fops;
599736
disk->private_data = nullb;
600737
disk->queue = nullb->q;
601-
sprintf(disk->disk_name, "nullb%d", nullb->index);
738+
strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
739+
602740
add_disk(disk);
741+
done:
603742
return 0;
604743

744+
out_cleanup_lightnvm:
745+
if (use_lightnvm)
746+
nvm_unregister(nullb->disk_name);
605747
out_cleanup_blk_queue:
606748
blk_cleanup_queue(nullb->q);
607749
out_cleanup_tags:
@@ -625,6 +767,12 @@ static int __init null_init(void)
625767
bs = PAGE_SIZE;
626768
}
627769

770+
if (use_lightnvm && queue_mode != NULL_Q_MQ) {
771+
pr_warn("null_blk: LightNVM only supported for blk-mq\n");
772+
pr_warn("null_blk: defaults queue mode to blk-mq\n");
773+
queue_mode = NULL_Q_MQ;
774+
}
775+
628776
if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
629777
if (submit_queues < nr_online_nodes) {
630778
pr_warn("null_blk: submit_queues param is set to %u.",

0 commit comments

Comments
 (0)