Commit e3eb3799 authored by Matias Bjørling's avatar Matias Bjørling Committed by Jens Axboe

lightnvm: core on-disk initialization

An Open-Channel SSD shall be initialized before use. To initialize, we
define an on-disk format, that keeps a small set of metadata to bring up
the media manager on top of the device.

The initial step is introduced to allow a user to format the disks for a
given media manager. During format, a system block is stored on one to
three separate luns on the device. Each lun has the system block
duplicated. During initialization, the system block can be retrieved and
the appropriate media manager can initialized.

The on-disk format currently covers (struct nvm_system_block):

 - Magic value "NVMS".
 - Monotonic increasing sequence number.
 - The physical block erase count.
 - Version of the system block format.
 - Media manager type.
 - Media manager superblock physical address.

The interface provides three functions to manage the system block:

 int nvm_init_sysblock(struct nvm_dev *, struct nvm_sb_info *)
 int nvm_get_sysblock(struct nvm *dev, struct nvm_sb_info *)
 int nvm_update_sysblock(struct nvm *dev, struct nvm_sb_info *)

Each implement a part of the logic to manage the system block. The
initialization creates the first system blocks and mark them on the
device. Get retrieves the latest system block by scanning all pages in
the associated system blocks. The update sysblock writes new metadata
and allocates new block if necessary.
Signed-off-by: default avatarMatias Bjørling <m@bjorling.me>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent ca5927e7
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
# Makefile for Open-Channel SSDs. # Makefile for Open-Channel SSDs.
# #
obj-$(CONFIG_NVM) := core.o obj-$(CONFIG_NVM) := core.o sysblk.o
obj-$(CONFIG_NVM_GENNVM) += gennvm.o obj-$(CONFIG_NVM_GENNVM) += gennvm.o
obj-$(CONFIG_NVM_RRPC) += rrpc.o obj-$(CONFIG_NVM_RRPC) += rrpc.o
...@@ -466,6 +466,7 @@ static int nvm_core_init(struct nvm_dev *dev) ...@@ -466,6 +466,7 @@ static int nvm_core_init(struct nvm_dev *dev)
dev->nr_chnls; dev->nr_chnls;
dev->total_pages = dev->total_blocks * dev->pgs_per_blk; dev->total_pages = dev->total_blocks * dev->pgs_per_blk;
INIT_LIST_HEAD(&dev->online_targets); INIT_LIST_HEAD(&dev->online_targets);
mutex_init(&dev->mlock);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -17,6 +17,7 @@ enum { ...@@ -17,6 +17,7 @@ enum {
#include <linux/types.h> #include <linux/types.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/dmapool.h> #include <linux/dmapool.h>
#include <uapi/linux/lightnvm.h>
enum { enum {
/* HW Responsibilities */ /* HW Responsibilities */
...@@ -281,6 +282,15 @@ struct nvm_block { ...@@ -281,6 +282,15 @@ struct nvm_block {
int state; int state;
}; };
/* system block cpu representation */
struct nvm_sb_info {
unsigned long seqnr;
unsigned long erase_cnt;
unsigned int version;
char mmtype[NVM_MMTYPE_LEN];
struct ppa_addr fs_ppa;
};
struct nvm_dev { struct nvm_dev {
struct nvm_dev_ops *ops; struct nvm_dev_ops *ops;
...@@ -329,6 +339,8 @@ struct nvm_dev { ...@@ -329,6 +339,8 @@ struct nvm_dev {
/* Backend device */ /* Backend device */
struct request_queue *q; struct request_queue *q;
char name[DISK_NAME_LEN]; char name[DISK_NAME_LEN];
struct mutex mlock;
}; };
static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev, static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
...@@ -394,6 +406,11 @@ static inline struct ppa_addr block_to_ppa(struct nvm_dev *dev, ...@@ -394,6 +406,11 @@ static inline struct ppa_addr block_to_ppa(struct nvm_dev *dev,
return ppa; return ppa;
} }
static inline int ppa_to_slc(struct nvm_dev *dev, int slc_pg)
{
return dev->lptbl[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_dev *, struct gendisk *, int, int); typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int);
...@@ -489,6 +506,24 @@ extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); ...@@ -489,6 +506,24 @@ extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *);
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);
/* sysblk.c */
#define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */
/* system block on disk representation */
struct nvm_system_block {
__be32 magic; /* magic signature */
__be32 seqnr; /* sequence number */
__be32 erase_cnt; /* erase count */
__be16 version; /* version number */
u8 mmtype[NVM_MMTYPE_LEN]; /* media manager name */
__be64 fs_ppa; /* PPA for media manager
* superblock */
};
extern int nvm_get_sysblock(struct nvm_dev *, struct nvm_sb_info *);
extern int nvm_update_sysblock(struct nvm_dev *, struct nvm_sb_info *);
extern int nvm_init_sysblock(struct nvm_dev *, struct nvm_sb_info *);
#else /* CONFIG_NVM */ #else /* CONFIG_NVM */
struct nvm_dev_ops; struct nvm_dev_ops;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#define NVM_TTYPE_NAME_MAX 48 #define NVM_TTYPE_NAME_MAX 48
#define NVM_TTYPE_MAX 63 #define NVM_TTYPE_MAX 63
#define NVM_MMTYPE_LEN 8
#define NVM_CTRL_FILE "/dev/lightnvm/control" #define NVM_CTRL_FILE "/dev/lightnvm/control"
......
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