Commit 8e53624d authored by Javier González's avatar Javier González Committed by Jens Axboe

lightnvm: eliminate nvm_lun abstraction in mm

In order to naturally support multi-target instances on an Open-Channel
SSD, targets should own the LUNs they get blocks from and manage
provisioning internally. This is done in several steps.

Since targets own the LUNs the are instantiated on top of and manage the
free block list internally, there is no need for a LUN abstraction in
the media manager. LUNs are intrinsically managed as in the physical
layout (ch:0,lun:0, ..., ch:0,lun:n, ch:1,lun:0, ch:1,lun:n, ...,
ch:m,lun:0, ch:m,lun:n) and given to the targets based on the target
creation ioctl. This simplifies LUN management and clears the path for a
partition manager to sit directly underneath LightNVM targets.
Signed-off-by: default avatarJavier González <javier@cnexlabs.com>
Signed-off-by: default avatarMatias Bjørling <m@bjorling.me>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 2a02e627
...@@ -203,15 +203,19 @@ int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas, ...@@ -203,15 +203,19 @@ int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
} }
EXPORT_SYMBOL(nvm_set_bb_tbl); EXPORT_SYMBOL(nvm_set_bb_tbl);
int nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
{ {
return dev->mt->submit_io(dev, rqd); struct nvm_dev *dev = tgt_dev->parent;
return dev->mt->submit_io(tgt_dev, rqd);
} }
EXPORT_SYMBOL(nvm_submit_io); EXPORT_SYMBOL(nvm_submit_io);
int nvm_erase_blk(struct nvm_dev *dev, struct ppa_addr *p, int flags) int nvm_erase_blk(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p, int flags)
{ {
return dev->mt->erase_blk(dev, p, flags); struct nvm_dev *dev = tgt_dev->parent;
return dev->mt->erase_blk(tgt_dev, p, flags);
} }
EXPORT_SYMBOL(nvm_erase_blk); EXPORT_SYMBOL(nvm_erase_blk);
...@@ -350,7 +354,7 @@ static int __nvm_submit_ppa(struct nvm_dev *dev, struct nvm_rq *rqd, int opcode, ...@@ -350,7 +354,7 @@ static int __nvm_submit_ppa(struct nvm_dev *dev, struct nvm_rq *rqd, int opcode,
nvm_generic_to_addr_mode(dev, rqd); nvm_generic_to_addr_mode(dev, rqd);
rqd->dev = dev; rqd->dev = NULL;
rqd->opcode = opcode; rqd->opcode = opcode;
rqd->flags = flags; rqd->flags = flags;
rqd->bio = bio; rqd->bio = bio;
......
This diff is collapsed.
...@@ -24,19 +24,37 @@ struct gen_dev { ...@@ -24,19 +24,37 @@ struct gen_dev {
struct nvm_dev *dev; struct nvm_dev *dev;
int nr_luns; int nr_luns;
struct nvm_lun *luns;
struct list_head area_list; struct list_head area_list;
struct mutex lock; struct mutex lock;
struct list_head targets; struct list_head targets;
}; };
/* Map between virtual and physical channel and lun */
struct gen_ch_map {
int ch_off;
int nr_luns;
int *lun_offs;
};
struct gen_dev_map {
struct gen_ch_map *chnls;
int nr_chnls;
};
struct gen_area { struct gen_area {
struct list_head list; struct list_head list;
sector_t begin; sector_t begin;
sector_t end; /* end is excluded */ sector_t end; /* end is excluded */
}; };
static inline void *ch_map_to_lun_offs(struct gen_ch_map *ch_map)
{
return ch_map + 1;
}
typedef int (gen_trans_fn)(struct nvm_tgt_dev *, struct ppa_addr *);
#define gen_for_each_lun(bm, lun, i) \ #define gen_for_each_lun(bm, lun, i) \
for ((i) = 0, lun = &(bm)->luns[0]; \ for ((i) = 0, lun = &(bm)->luns[0]; \
(i) < (bm)->nr_luns; (i)++, lun = &(bm)->luns[(i)]) (i) < (bm)->nr_luns; (i)++, lun = &(bm)->luns[(i)])
......
This diff is collapsed.
...@@ -74,7 +74,9 @@ struct rrpc_block { ...@@ -74,7 +74,9 @@ struct rrpc_block {
struct rrpc_lun { struct rrpc_lun {
struct rrpc *rrpc; struct rrpc *rrpc;
struct nvm_lun *parent;
int id;
struct ppa_addr bppa;
struct rrpc_block *cur, *gc_cur; struct rrpc_block *cur, *gc_cur;
struct rrpc_block *blocks; /* Reference to block allocation */ struct rrpc_block *blocks; /* Reference to block allocation */
...@@ -107,7 +109,6 @@ struct rrpc { ...@@ -107,7 +109,6 @@ struct rrpc {
struct gendisk *disk; struct gendisk *disk;
sector_t soffset; /* logical sector offset */ sector_t soffset; /* logical sector offset */
u64 poffset; /* physical page offset */
int nr_luns; int nr_luns;
struct rrpc_lun *luns; struct rrpc_lun *luns;
...@@ -164,14 +165,37 @@ struct rrpc_rev_addr { ...@@ -164,14 +165,37 @@ struct rrpc_rev_addr {
u64 addr; u64 addr;
}; };
static inline struct ppa_addr rrpc_linear_to_generic_addr(struct nvm_geo *geo,
struct ppa_addr r)
{
struct ppa_addr l;
int secs, pgs;
sector_t ppa = r.ppa;
l.ppa = 0;
div_u64_rem(ppa, geo->sec_per_pg, &secs);
l.g.sec = secs;
sector_div(ppa, geo->sec_per_pg);
div_u64_rem(ppa, geo->pgs_per_blk, &pgs);
l.g.pg = pgs;
return l;
}
static inline struct ppa_addr rrpc_recov_addr(struct nvm_dev *dev, u64 pba)
{
return linear_to_generic_addr(&dev->geo, pba);
}
static inline u64 rrpc_blk_to_ppa(struct rrpc *rrpc, struct rrpc_block *rblk) static inline u64 rrpc_blk_to_ppa(struct rrpc *rrpc, struct rrpc_block *rblk)
{ {
struct nvm_tgt_dev *dev = rrpc->dev; struct nvm_tgt_dev *dev = rrpc->dev;
struct nvm_geo *geo = &dev->geo; struct nvm_geo *geo = &dev->geo;
struct rrpc_lun *rlun = rblk->rlun; struct rrpc_lun *rlun = rblk->rlun;
struct nvm_lun *lun = rlun->parent;
return (lun->id * geo->sec_per_lun) + (rblk->id * geo->sec_per_blk); return (rlun->id * geo->sec_per_lun) + (rblk->id * geo->sec_per_blk);
} }
static inline sector_t rrpc_get_laddr(struct bio *bio) static inline sector_t rrpc_get_laddr(struct bio *bio)
......
...@@ -371,6 +371,9 @@ static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb, ...@@ -371,6 +371,9 @@ static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb,
return -EINVAL; return -EINVAL;
} }
/* Transform physical address to target address space */
nvmdev->mt->part_to_tgt(nvmdev, entries, cmd_nlb);
if (update_l2p(cmd_slba, cmd_nlb, entries, priv)) { if (update_l2p(cmd_slba, cmd_nlb, entries, priv)) {
ret = -EINTR; ret = -EINTR;
goto out; goto out;
......
...@@ -47,6 +47,7 @@ struct ppa_addr { ...@@ -47,6 +47,7 @@ struct ppa_addr {
struct nvm_rq; struct nvm_rq;
struct nvm_id; struct nvm_id;
struct nvm_dev; struct nvm_dev;
struct nvm_tgt_dev;
typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *); typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
...@@ -210,7 +211,6 @@ struct nvm_id { ...@@ -210,7 +211,6 @@ struct nvm_id {
struct nvm_target { struct nvm_target {
struct list_head list; struct list_head list;
struct list_head lun_list;
struct nvm_tgt_dev *dev; struct nvm_tgt_dev *dev;
struct nvm_tgt_type *type; struct nvm_tgt_type *type;
struct gendisk *disk; struct gendisk *disk;
...@@ -231,7 +231,7 @@ typedef void (nvm_end_io_fn)(struct nvm_rq *); ...@@ -231,7 +231,7 @@ typedef void (nvm_end_io_fn)(struct nvm_rq *);
struct nvm_rq { struct nvm_rq {
struct nvm_tgt_instance *ins; struct nvm_tgt_instance *ins;
struct nvm_dev *dev; struct nvm_tgt_dev *dev;
struct bio *bio; struct bio *bio;
...@@ -266,15 +266,6 @@ static inline void *nvm_rq_to_pdu(struct nvm_rq *rqdata) ...@@ -266,15 +266,6 @@ static inline void *nvm_rq_to_pdu(struct nvm_rq *rqdata)
return rqdata + 1; return rqdata + 1;
} }
struct nvm_lun {
int id;
int lun_id;
int chnl_id;
struct list_head list;
};
enum { enum {
NVM_BLK_ST_FREE = 0x1, /* Free block */ NVM_BLK_ST_FREE = 0x1, /* Free block */
NVM_BLK_ST_TGT = 0x2, /* Block in use by target */ NVM_BLK_ST_TGT = 0x2, /* Block in use by target */
...@@ -321,6 +312,9 @@ struct nvm_tgt_dev { ...@@ -321,6 +312,9 @@ struct nvm_tgt_dev {
/* Device information */ /* Device information */
struct nvm_geo geo; struct nvm_geo geo;
/* Base ppas for target LUNs */
struct ppa_addr *luns;
sector_t total_secs; sector_t total_secs;
struct nvm_id identity; struct nvm_id identity;
...@@ -330,6 +324,7 @@ struct nvm_tgt_dev { ...@@ -330,6 +324,7 @@ struct nvm_tgt_dev {
struct nvm_dev_ops *ops; struct nvm_dev_ops *ops;
void *parent; void *parent;
void *map;
}; };
struct nvm_dev { struct nvm_dev {
...@@ -363,16 +358,18 @@ struct nvm_dev { ...@@ -363,16 +358,18 @@ struct nvm_dev {
char name[DISK_NAME_LEN]; char name[DISK_NAME_LEN];
void *private_data; void *private_data;
void *rmap;
struct mutex mlock; struct mutex mlock;
spinlock_t lock; spinlock_t lock;
}; };
static inline struct ppa_addr linear_to_generic_addr(struct nvm_geo *geo, static inline struct ppa_addr linear_to_generic_addr(struct nvm_geo *geo,
struct ppa_addr r) u64 pba)
{ {
struct ppa_addr l; struct ppa_addr l;
int secs, pgs, blks, luns; int secs, pgs, blks, luns;
sector_t ppa = r.ppa; sector_t ppa = pba;
l.ppa = 0; l.ppa = 0;
...@@ -465,8 +462,7 @@ static inline int ppa_to_slc(struct nvm_dev *dev, int slc_pg) ...@@ -465,8 +462,7 @@ static inline int ppa_to_slc(struct nvm_dev *dev, int slc_pg)
typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *); typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *);
typedef sector_t (nvm_tgt_capacity_fn)(void *); typedef sector_t (nvm_tgt_capacity_fn)(void *);
typedef void *(nvm_tgt_init_fn)(struct nvm_tgt_dev *, struct gendisk *, typedef void *(nvm_tgt_init_fn)(struct nvm_tgt_dev *, struct gendisk *);
struct list_head *lun_list);
typedef void (nvm_tgt_exit_fn)(void *); typedef void (nvm_tgt_exit_fn)(void *);
struct nvm_tgt_type { struct nvm_tgt_type {
...@@ -499,10 +495,11 @@ typedef void (nvmm_unregister_fn)(struct nvm_dev *); ...@@ -499,10 +495,11 @@ typedef void (nvmm_unregister_fn)(struct nvm_dev *);
typedef int (nvmm_create_tgt_fn)(struct nvm_dev *, struct nvm_ioctl_create *); typedef int (nvmm_create_tgt_fn)(struct nvm_dev *, struct nvm_ioctl_create *);
typedef int (nvmm_remove_tgt_fn)(struct nvm_dev *, struct nvm_ioctl_remove *); typedef int (nvmm_remove_tgt_fn)(struct nvm_dev *, struct nvm_ioctl_remove *);
typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); typedef int (nvmm_submit_io_fn)(struct nvm_tgt_dev *, struct nvm_rq *);
typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct ppa_addr *, int); typedef int (nvmm_erase_blk_fn)(struct nvm_tgt_dev *, struct ppa_addr *, int);
typedef int (nvmm_get_area_fn)(struct nvm_dev *, sector_t *, sector_t); typedef int (nvmm_get_area_fn)(struct nvm_dev *, sector_t *, sector_t);
typedef void (nvmm_put_area_fn)(struct nvm_dev *, sector_t); typedef void (nvmm_put_area_fn)(struct nvm_dev *, sector_t);
typedef void (nvmm_part_to_tgt_fn)(struct nvm_dev *, sector_t*, int);
struct nvmm_type { struct nvmm_type {
const char *name; const char *name;
...@@ -520,6 +517,8 @@ struct nvmm_type { ...@@ -520,6 +517,8 @@ struct nvmm_type {
nvmm_get_area_fn *get_area; nvmm_get_area_fn *get_area;
nvmm_put_area_fn *put_area; nvmm_put_area_fn *put_area;
nvmm_part_to_tgt_fn *part_to_tgt;
struct list_head list; struct list_head list;
}; };
...@@ -533,14 +532,18 @@ extern void nvm_unregister(struct nvm_dev *); ...@@ -533,14 +532,18 @@ extern void nvm_unregister(struct nvm_dev *);
extern int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, extern int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas,
int nr_ppas, int type); int nr_ppas, int type);
extern int nvm_submit_io(struct nvm_dev *, struct nvm_rq *); extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *); extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *);
extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *); extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *);
extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *, extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *,
const struct ppa_addr *, int, int); const struct ppa_addr *, int, int);
extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *);
extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int, int); extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int, int);
extern int nvm_erase_blk(struct nvm_dev *, struct ppa_addr *, int); extern int nvm_erase_blk(struct nvm_tgt_dev *, struct ppa_addr *, int);
extern int nvm_get_l2p_tbl(struct nvm_dev *, u64, u32, nvm_l2p_update_fn *,
void *);
extern int nvm_get_area(struct nvm_dev *, sector_t *, sector_t);
extern void nvm_put_area(struct nvm_dev *, sector_t);
extern void nvm_end_io(struct nvm_rq *, int); extern void nvm_end_io(struct nvm_rq *, int);
extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int, extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int,
void *, int); void *, int);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment