comparasion of each Headerfile ( pblk vs rrpc )

gennvm.h

lightnvm.h

rrpc.h

LightNVM’s function calls

Check if the kernel support LightNVM.

2. int nvme_nvm_ns_supported(struct nvme_ns *ns,struct nvme_id_ns *id)

From linux/drivers/nvme/host/lightnvm.c

630 /* move to shared place when used in multiple places. */
631 #define PCI_VENDOR_ID_CNEX 0x1d1d
632 #define PCI_DEVICE_ID_CNEX_WL 0x2807
633 #define PCI_DEVICE_ID_CNEX_QEMU 0x1f1f
634 
635 int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id)
636 {
637         struct nvme_ctrl *ctrl = ns->ctrl;
638         /* XXX: this is poking into PCI structures from generic code! */
639         struct pci_dev *pdev = to_pci_dev(ctrl->dev);
640 
641         /* QEMU NVMe simulator - PCI ID + Vendor specific bit */
642         if (pdev->vendor == PCI_VENDOR_ID_CNEX &&
643                                 pdev->device == PCI_DEVICE_ID_CNEX_QEMU &&
644                                                         id->vs[0] == 0x1)
645                 return 1; 
.......
660         return 0;
661 }

The following shows you which calls the above function.

1. static void nvme_alloc_ns(struct nvme_ctrl * ctrl, unsigned nsid)

From linux/drivers/nvme/host/core.c

1651 static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
1652 {
1653         struct nvme_ns *ns;
1654         struct gendisk *disk;
1655         struct nvme_id_ns *id;
1656         char disk_name[DISK_NAME_LEN];
1657         int node = dev_to_node(ctrl->dev);
....... 
1686         if (nvme_nvm_ns_supported(ns, id)) {
1687                 if (nvme_nvm_register(ns, disk_name, node,
1688                                                         &nvme_ns_attr_group)) {
1689                         dev_warn(ctrl->dev, "%s: LightNVM init failure\n",
1690                                                                 __func__);
1691                         goto out_free_id;
1692                 }
1693         } else {
.......
1706         }
.......
1719         device_add_disk(ctrl->device, ns->disk);
.......
1724         return;
.......
1733 }

3. int nvme_nvm_resgiter(struct nvme_ns *ns, char *disk_name, int node, const struct attribute_group *attrs)

from linux/drivers/nvme/host/nvme.h

  • struct nvme_ns
149 /*
150  * An NVM Express namespace is equivalent to a SCSI LUN
151  */
152 struct nvme_ns {
153         struct list_head list;
154 
155         struct nvme_ctrl *ctrl;
156         struct request_queue *queue;
157         struct gendisk *disk;
158         struct nvm_dev *ndev;          // new addition in pblk kernel version.
159         struct kref kref;
.......
177 };

from linux/drivers/nvme/host/nvme.h

98 struct nvme_ctrl {
 99         enum nvme_ctrl_state state;
100         spinlock_t lock;
101         const struct nvme_ctrl_ops *ops;
102         struct request_queue *admin_q;
103         struct request_queue *connect_q;
.....
107         struct blk_mq_tag_set *tagset;
108         struct list_head namespaces;
109         struct mutex namespaces_mutex;
110         struct device *device;  /* char device */
.....
147 };

From linux/drivers/nvme/host/lightnvm.c

596 int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node,
597                       const struct attribute_group *attrs)
598 {
599         struct request_queue *q = ns->queue;
600         struct nvm_dev *dev;
.....
607         dev->q = q;
608         memcpy(dev->name, disk_name, DISK_NAME_LEN);
609         dev->ops = &nvme_nvm_dev_ops;
610         dev->parent_dev = ns->ctrl->device;
611         dev->private_data = ns;
612         ns->ndev = dev;
613 
614         ret = nvm_register(dev);
.....
621         return ret;
622 }

4. int nvm_register(struct nvm_dev *dev)

from linux/drivers/lightnvm/core.c

 729 int nvm_register(struct nvm_dev *dev)
 730 {
 731         int ret;
 732 
 733         ret = nvm_init(dev);
 .....
 752         ret = nvm_sysfs_register_dev(dev);
 .....
 756         if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) {
 757                 ret = nvm_get_sysblock(dev, &dev->sb);
 758                 if (!ret)
 759                         pr_err("nvm: device not initialized.\n");
 760                 else if (ret < 0)
 761                         pr_err("nvm: err (%d) on device initialization\n", ret);
 762         }
 763 
 764         /* register device with a supported media manager */
 765         down_write(&nvm_lock);
 766         if (ret > 0)
 767                 dev->mt = nvm_init_mgr(dev);
 768         list_add(&dev->devices, &nvm_devices);
 769         up_write(&nvm_lock);
 770 
 771         return 0;
 ......
 777 }

5. int nvm_get_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info)

form linux/include/lightnvme.h

  • nvm_system_block
583 /* sysblk.c */
584 #define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */
585 
586 /* system block on disk representation */
587 struct nvm_system_block {
588         __be32                  magic;          /* magic signature */
589         __be32                  seqnr;          /* sequence number */
590         __be32                  erase_cnt;      /* erase count */
591         __be16                  version;        /* version number */
592         u8                      mmtype[NVM_MMTYPE_LEN]; /* media manager name */
593         __be64                  fs_ppa;         /* PPA for media manager
594                                                  * superblock */
595 };
  • nvm_sb_info
298 /* system block cpu representation */
299 struct nvm_sb_info {
300         unsigned long           seqnr;
301         unsigned long           erase_cnt;
302         unsigned int            version;
303         char                    mmtype[NVM_MMTYPE_LEN];
304         struct ppa_addr         fs_ppa;
305 };

from linux/drivers/lightnvm/sysblk.c

373 int nvm_get_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info)
374 {
375         struct ppa_addr sysblk_ppas[MAX_SYSBLKS];
376         struct sysblk_scan s;
377         struct nvm_system_block *cur;
......
381         /*
382          * 1. setup sysblk locations
383          * 2. get bad block list
384          * 3. filter on host-specific (type 3)
385          * 4. iterate through all and find the highest seq nr.
386          * 5. return superblock information
387          */
....
392         nvm_setup_sysblk_scan(dev, &s, sysblk_ppas);
393 
394         mutex_lock(&dev->mlock);
395         ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0);
......
399         /* no sysblocks initialized */
400         if (!s.nr_ppas)
401                 goto err_sysblk;
.....
407         /* find the latest block across all sysblocks */
408         for (i = 0; i < s.nr_rows; i++) {
409                 for (j = 0; j < MAX_BLKS_PR_SYSBLK; j++) {
410                         struct ppa_addr ppa = s.ppas[scan_ppa_idx(i, j)];
411 
412                         ret = nvm_scan_block(dev, &ppa, cur);
.....
417                 }
418         }
419 
420         nvm_sysblk_to_cpu(info, cur);
......
428         return ret;
429 }

So far, just after booting, initialization —

From now on just, How sumbit IO function

from linux/drivers/lightnmv/gennvm.c

  • gen_submit_io
754 static int gen_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
755 {
756         if (!dev->ops->submit_io)
757                 return -ENODEV;
758 
759         /* Convert address space */
760         nvm_generic_to_addr_mode(dev, rqd);
761 
762         rqd->dev = dev;
763         rqd->end_io = gen_end_io;
764         return dev->ops->submit_io(dev, rqd);
765 }

from linux/drivers/lightnvm/core.c

  • void nvm_generic_to_addr_mode(struct nvme_dev *dev, struct nvme_rq *rqd)
282 void nvm_generic_to_addr_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
 283 {
 284         int i;
 285 
 286         if (rqd->nr_ppas > 1) {
 287                 for (i = 0; i < rqd->nr_ppas; i++)
 288                         rqd->ppa_list[i] = generic_to_dev_addr(dev,
 289                                                         rqd->ppa_list[i]);
 290         } else {
 291                 rqd->ppa_addr = generic_to_dev_addr(dev, rqd->ppa_addr);
 292         }
 293 }
 294 EXPORT_SYMBOL(nvm_generic_to_addr_mode);

from include/linux/lightnvm.h

  • struct nvm_dev_ops
 65 struct nvm_dev_ops {
 66         nvm_id_fn               *identity;
 67         nvm_get_l2p_tbl_fn      *get_l2p_tbl;
 68         nvm_op_bb_tbl_fn        *get_bb_tbl;
 69         nvm_op_set_bb_fn        *set_bb_tbl;
 70 
 71         nvm_submit_io_fn        *submit_io;
 72         nvm_erase_blk_fn        *erase_block;
 73 
 74         nvm_create_dma_pool_fn  *create_dma_pool;
 75         nvm_destroy_dma_pool_fn *destroy_dma_pool;
 76         nvm_dev_dma_alloc_fn    *dev_dma_alloc;
 77         nvm_dev_dma_free_fn     *dev_dma_free;
 78 
 79         unsigned int            max_phys_sect;
 80 };

from linux/drivers/nvme/host/lightnvm.c

  • maching the above part with function in NVMe driver code
577 static struct nvm_dev_ops nvme_nvm_dev_ops = {
578         .identity               = nvme_nvm_identity,
579 
580         .get_l2p_tbl            = nvme_nvm_get_l2p_tbl,
581 
582         .get_bb_tbl             = nvme_nvm_get_bb_tbl,
583         .set_bb_tbl             = nvme_nvm_set_bb_tbl,
584 
585         .submit_io              = nvme_nvm_submit_io,
586         .erase_block            = nvme_nvm_erase_block,
587 
588         .create_dma_pool        = nvme_nvm_create_dma_pool,
589         .destroy_dma_pool       = nvme_nvm_destroy_dma_pool,
590         .dev_dma_alloc          = nvme_nvm_dev_dma_alloc,
591         .dev_dma_free           = nvme_nvm_dev_dma_free,
592 
593         .max_phys_sect          = 64,
594 };

static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)

from linux/drivers/nvme/host/lightnvm.c

495 static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
496 {
497         struct request_queue *q = dev->q;
498         struct nvme_ns *ns = q->queuedata;
499         struct request *rq;
500         struct bio *bio = rqd->bio;
501         struct nvme_nvm_command *cmd;
..... 
523         nvme_nvm_rqtocmd(rq, rqd, ns, cmd);
.....
531         blk_execute_rq_nowait(q, NULL, rq, 0, nvme_nvm_end_io);
532 
533         return 0;
534 }

void blk_execute_rq_nowait(struc request_queue *q, struct gendisk *bd_disk, struct request *rq, int at_head, rq_end_io_fn *done)

from linux/block/blk-exec.c

 36 /**
 37  * blk_execute_rq_nowait - insert a request into queue for execution
 38  * @q:          queue to insert the request in
 39  * @bd_disk:    matching gendisk
 40  * @rq:         request to insert
 41  * @at_head:    insert request at head or tail of queue
 42  * @done:       I/O completion handler
 43  *
 44  * Description:
 45  *    Insert a fully prepared request at the back of the I/O scheduler queue
 46  *    for execution.  Don't wait for completion.
 47  *
 48  * Note:
 49  *    This function will invoke @done directly if the queue is dead.
 50  */
 51 void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
 52                            struct request *rq, int at_head,
 53                            rq_end_io_fn *done)
 54 {
 55         int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
.....
 63         /*
 64          * don't check dying flag for MQ because the request won't
 65          * be reused after dying flag is set
 66          */
 67         if (q->mq_ops) {
 68                 blk_mq_insert_request(rq, at_head, true, false);
 69                 return;
 70         }
.....
 81 
 82         __elv_add_request(q, rq, where);
 83         __blk_run_queue(q);
 84         spin_unlock_irq(q->queue_lock);
 85 }
 86 EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
  • Why do they transfer to blk-mq ???

linux/include/lightnvm.h

307 struct nvm_dev {
308         struct nvm_dev_ops *ops;
309 
310         struct list_head devices;
311 
312         /* Media manager */
313         struct nvmm_type *mt;
314         void *mp;
315 
316         /* System blocks */
317         struct nvm_sb_info sb;
318 
319         /* Device information */
320         int nr_chnls;
321         int nr_planes;
322         int luns_per_chnl;
323         int sec_per_pg; /* only sectors for a single page */
324         int pgs_per_blk;
325         int blks_per_lun;
326         int fpg_size;
327         int pfpg_size; /* size of buffer if all pages are to be read */
328         int sec_size;
329         int oob_size;
330         int mccap;
331         struct nvm_addr_format ppaf;
332 
333         /* Calculated/Cached values. These do not reflect the actual usable
334          * blocks at run-time.
335          */
336         int max_rq_size;
337         int plane_mode; /* drive device in single, double or quad mode */
338 
339         int sec_per_pl; /* all sectors across planes */
340         int sec_per_blk;
341         int sec_per_lun;
342 
343         /* lower page table */
344         int lps_per_blk;
345         int *lptbl;
346 
347         unsigned long total_secs;
348         int nr_luns;
349 
350         unsigned long *lun_map;
351         void *dma_pool;
352 
353         struct nvm_id identity;
354 
355         /* Backend device */
356         struct request_queue *q;
357         struct device dev;
358         struct device *parent_dev;
359         char name[DISK_NAME_LEN];
360         void *private_data;
361 
362         struct mutex mlock;
363         spinlock_t lock;
364 };

lightNVM.h

struct nvm_lun_mgmt {

struct nvm_lun_mgmt {
        /* lun block lists */
        struct list_head used_list;     /* In-use blocks */
        struct list_head free_list;     /* Not used blocks i.e. released
                                         * and ready for use
                                         */
        struct list_head bb_list;       /* Bad blocks. Mutually exclusive with
                                         * free_list and used_list
                                         */

        unsigned int nr_free_blocks;    /* Number of unused blocks */
};

gennvm.h

struct gen_lun {

struct gen_lun {
        struct nvm_lun vlun;

        /* A LUN can either be managed by the media manager if it is shared
         * among several used through the generic get/put block interface or
         * exclusively owned by a target. In this case, the target manages
         * the LUN. gen_lun always maintains a reference to the LUN management.
         *
         * Exclusive access is managed by the dev->lun_map bitmask. 0:
         * non-exclusive, 1: exclusive.
         */
        struct nvm_lun_mgmt *mgmt;
        struct nvm_target *tgt;
};

struct gen_dev {

struct gen_dev {
        struct nvm_dev *dev;  // nvme device

        int nr_luns;  // the number of luns. 
        struct gen_lun *luns; // the above struct, gen_lun
        struct list_head area_list; // ??

        struct mutex lock;
        struct list_head targets; // ?? 
};

struct gen_area {

struct gen_area {
        struct list_head list;
        sector_t begin;
        sector_t end;   /* end is excluded */
};

gennvm.c

function list of gennvm.c

1. 
static struct attribute gen_type_attr = {
        .name = "type",
        .mode = S_IRUGO
};

2.
static struct attribute *gen_target_attrs[] = {
        &gen_type_attr,
        NULL,
};

3.
static const struct sysfs_ops target_sysfs_ops = {
        .show = gen_target_attr_show,
        .store = gen_target_attr_store,
};

4.
static struct kobj_type nvm_target_type = {
        .sysfs_ops      = &target_sysfs_ops,
        .default_attrs  = gen_target_attrs,
        .release        = gen_target_release
};

5. 
static const struct block_device_operations gen_fops = {
        .owner          = THIS_MODULE,
};

6. 
static DEVICE_ATTR(blocks, S_IRUGO, gen_sysfs_show, NULL);

7.
static struct attribute *gen_attrs[] = {
        &dev_attr_blocks.attr,
        NULL,
};

8.
static struct attribute_group gen_attr_group = {
        .name = "mediamgr",
        .attrs = gen_attrs,
};

9.
static struct nvmm_type gen = {
        .name                   = "gennvm",
        .version                = {0, 1, 0},

        .register_mgr           = gen_register,
        .unregister_mgr         = gen_unregister,

        .create_tgt             = gen_create_tgt,
        .remove_tgt             = gen_remove_tgt,

        .get_blk                = gen_get_blk,
        .put_blk                = gen_put_blk,

        .submit_io              = gen_submit_io,
        .erase_blk              = gen_erase_blk,

        .mark_blk               = gen_mark_blk,

        .get_lun                = gen_get_lun,
        .reserve_lun            = gen_reserve_lun,
        .release_lun            = gen_release_lun,
        .lun_info_print         = gen_lun_info_print,

        .get_area               = gen_get_area,
        .put_area               = gen_put_area,

};

lists of static struct nvmm_type gen = {

.register_mgr = gen_register

static int gen_register(struct nvm_dev *dev)

                                  |---  initialize **struct gen_dev**
                                  |---  ret = gen_luns_init(dev(struct nvm_dev), gn) |--- initialize struct nvm_lun_mgmt of struct gen_lun
gen -> register_mgr(gen_register) |  
                                  |---  ret = gen_blocks_init(dev(struct nvm_dev), gn) |--- initialize struct nvme_block with truct gen_lnu
                                  |                                                    |--- if (dev->ops->get_bb_tbl)  |--- ret = nvm_get_bb_tbl(dev, ppa, blks);
                                                                                                                       |--- ret = gen_block_bb(gn, ppa, blks, nr_blks);
                                                                                       |--- if (dev->identity.dom & NVM_RSP_L2P && dev->ops->get_l2p_tbl)                                                                                              |--- ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_secs,
                                                        gen_block_map, dev); 
                                  |---  if (sysfs_create_group(&dev->dev.kobj, &gen_attr_group))
                                  |--- return 1;

.unregister_mgr = gen_unregister

static void gen_unregister(struct nvm_dev *dev)
                                      |--- _gen_remove_target(t(nvm_target)) |--- gen_unregister_target(t(nvm_target))
                                      |
gen -> unregister_mgr(gen_unregister) |--- sysfs_remove_group(&dev->dev.kobj, &gen_attr_group);
                                      |
                                      |--- gen_free(dev);

.create_tgt = gen_create_tgt

static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)

this part means handling create command of lnvm tool about create

                                  |--- tt(struct nvm_tgt_type) = nvm_find_target_type(create->tgttype, 1);
                                  |--- t(struct nvm_target) = gen_find_target(gn, create->tgtname);
gen -> create_tgt(gen_create_tgt) |--- tqueue(request_queue) = blk_alloc_queue_node(GFP_KERNEL, dev->q->node);
                                  |--- blk_queue_make_request(tqueue, tt->make_rq);
                                  |--- targetdata = tt->init(dev, tdisk, s->lun_begin, s->lun_end);
                                  |--- return 0;

.remove_tgt = gen_remove_tgt

static int gen_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)

This part handling remove command of lnvm

/**

  • gen_remove_tgt - Removes a target from the media manager
  • @dev: device
  • @remove: ioctl structure with target name to remove. *
  • Returns:
  • 0: on success
  • 1: on not found
  • <0: on error */
                                  | --- t(nvm_target) = gen_find_target(gn, remove->tgtname);
gen -> remove_tgt(gen_remove_tgt) |
                                  | --- __gen_remove_target(t(nvm_target)); | --- gen_unregister_target(t(nvm_target));
                                  | --- return 0;                            

.get_blk = gen_get_blk

static struct nvm_block *gen_get_blk(struct nvm_dev *dev, struct nvm_lun *vlun)

get free blocks.

                            | --- blk(nvme_blk) = list_first_entry(&lun->mgmt->free_list, struct nvm_block, list);
gen -> get_blk(gen_get_blk) |
                            | --- return blk;

.put_blk = gen_get_blk

static void gen_put_blk(struct nvm_dev *dev, struct nvm_block *blk)

                            | --- if (blk->state & NVM_BLK_ST_TGT)
gen -> put_blk(gen_get_blk) | --- else if (blk->state & NVM_BLK_ST_BAD)
                            | --- else

.submit_io = gen_submit_io

static int gen_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)

                                     /* Convert address space */
                                |--- nvm_generic_to_addr_mode(dev, rqd);
gen -> submit_io(gen_submit_io) | 
                                |--- return dev->ops->submit_io(dev, rqd);

.erase_blk = gen_erase_blk

static int gen_erase_blk(struct nvm_dev *dev, struct nvm_blk, int flags)

                                  |--- struct ppa_addr addr = block_to_ppa(dev, blk);
gen -> create_tgt(gen_remove_tgt) |
                                  |--- return nvm_erase_ppa(dev, &addr, 1, flags);  

.mark_blk = gen_mark_blk

static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr gen_ppa, int type)

                                  | --- pr_debug("gen: ppa  (ch: %u lun: %u blk: %u pg: %u) -> %u\n",gen_ppa.g.ch,gen_ppa.g.lun, gen_ppa.g.blk,gen_ppa.g.pg, type);
                                  | --- if (unlikely(gen_ppa.g.ch > dev->nr_chnls || gen_ppa.g.lun > dev->luns_per_chnl || gen_ppa.g.blk > dev->blks_per_lun)) {
gen -> create_tgt(gen_remove_tgt) | 
                                  | /* will be moved to bb list on put_blk from target */ 
                                     blk->state = type;

.get_lun = gen_get_lun

static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid)

                                  | --- struct gen_dev *gn = dev->mp;
gen -> get_lun(gen_get_lun) | 
                                  | --- return &gn->luns[lunid].vlun;

.reserve_lun = gen_reserve_lun

static struct nvm_lun_mgmt *gen_reserve_lun(struct nvm_dev *dev, int lunid, struct gendisk *tdisk)

                                    | --- lun = &gn->luns[lunid];
                                    | --- mgmt = lun -> mgmt;
gen -> reserve_lun(gen_reserve_lun) | 
                                    | --- lun->tgt = gen_find_target(gn, tdisk->disk_name);
                                    | --- return mgmt;

.release_lun = gen_release_lun

static void gen_release_lun(struct nvm_dev *dev, int lunid, struct nvm_lun_mgmt *mgmt)

                                    | --- lun = &gn->luns[lunid];  
gen -> release_lun(gen_release_lun) |
                                    | --- lun->mgmt = mgmt;

.lun_info_print = gen_lun_info_print

static void gen_lun_info_print(struct nvm_dev *dev)

                                  | ---  gen_for_each_lun(gn, lun, i){
                                  |
gen -> create_tgt(gen_remove_tgt) |      pr_info("%s: lun%8u\t%u\n", dev->name, i,
                                                lun->mgmt->nr_free_blocks);
                                  | }

.get_area = gen_get_area

satic int gen_get_area(struct nvm_dev *dev, sector_t *lba, sector_t len)

                                  | --- area->begin = *lba = begin;
gen -> create_tgt(gen_remove_tgt) | --- area->end = begin + len;
                                  | --- return 0;

.put_area = gen_put_area

static void gen_put_area(struct nvm_dev *dev, sector_t begin)

gen -> create_tgt(gen_remove_tgt) | --- list_del(&area->list);

total function list of gennvm.c file

1. static int __init gen_module_init(void)

2. static void gen_module_exit(void)

3. static void gen_lun_info_print(struct nvm_dev *dev)

4. static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid)

5. static void gen_release_lun(struct nvm_dev *dev, int lunid, struct nvm_lun_mgmt *mgmt)

6. static struct nvm_lun_mgmt *gen_reserve_lun(struct nvm_dev *dev, int lunid, struct gendisk *tdisk)

7. static int gen_erase_blk(struct nvm_dev *dev, struct nvm_block *blk, int flags)

8. static int gen_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)

9. static void gen_end_io(struct nvm_rq *rqd)

10. static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr gen_ppa, int type)

11. static void gen_put_blk(struct nvm_dev *dev, struct nvm_block *blk)

12. static struct nvm_block *gen_get_blk(struct nvm_dev *dev, struct nvm_lun *vlun)

13. static void gen_unregister(struct nvm_dev *dev)

14. static int gen_register(struct nvm_dev *dev)

15. static ssize_t gen_sysfs_show(struct device *dev, struct device_attribute *dattr, char *page)

16. static ssize_t gen_sysfs_blocks(struct nvm_dev *dev, char *page)

17. static void gen_free(struct nvm_dev *dev)

18. static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn)

19. static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private)

20. static int gen_block_bb(struct gen_dev *gn, struct ppa_addr ppa, u8 *blks, int nr_blks)

21. static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn)

22. static void gen_luns_free(struct nvm_dev *dev)

23. static void gen_blocks_free(struct nvm_dev *dev)

24. static void gen_put_area(struct nvm_dev *dev, sector_t begin)

25. static int gen_get_area(struct nvm_dev *dev, sector_t *lba, sector_t len)

26. static int gen_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)

27. static void __gen_remove_target(struct nvm_target *t)

28. static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)

29. static struct nvm_target *gen_find_target(struct gen_dev *gn, const char *name)

30. int gen_register_target(struct nvm_target *t)

31. void gen_unregister_target(struct nvm_target *t)

32. static void gen_target_release(struct kobject *kobj)

33. static ssize_t gen_target_attr_store(struct kobject *kobj,struct attribute *attr,const char *page, size_t len)

34. static ssize_t gen_target_attr_show(struct kobject *kobj,struct attribute *attr,char *page)

Data structure of lightNVM

/include/linux/lightnvm.h

struct nvm_lun_mgmt {

struct nvm_lun_mgmt {
        /* lun block lists */
        struct list_head used_list;     /* In-use blocks */
        struct list_head free_list;     /* Not used blocks i.e. released
                                         * and ready for use
                                         */
        struct list_head bb_list;       /* Bad blocks. Mutually exclusive with
                                         * free_list and used_list
                                         */

        unsigned int nr_free_blocks;    /* Number of unused blocks */
};