mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
lightnvm: set target over-provision on create ioctl
Allow to set the over-provision percentage on target creation. In case that the value is not provided, fall back to the default value set by the target. In pblk, set the default OP to 11% of the total size of the device Signed-off-by: Javier González <[email protected]> Signed-off-by: Hans Holmberg <[email protected]> Signed-off-by: Matias Bjørling <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
This commit is contained in:
parent
a7689938ef
commit
e53927393b
5 changed files with 104 additions and 24 deletions
|
|
@ -140,7 +140,8 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
|
|||
}
|
||||
|
||||
static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
|
||||
int lun_begin, int lun_end)
|
||||
u16 lun_begin, u16 lun_end,
|
||||
u16 op)
|
||||
{
|
||||
struct nvm_tgt_dev *tgt_dev = NULL;
|
||||
struct nvm_dev_map *dev_rmap = dev->rmap;
|
||||
|
|
@ -219,6 +220,7 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
|
|||
tgt_dev->geo.nr_chnls = nr_chnls;
|
||||
tgt_dev->geo.all_luns = nr_luns;
|
||||
tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
|
||||
tgt_dev->geo.op = op;
|
||||
tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
|
||||
tgt_dev->q = dev->q;
|
||||
tgt_dev->map = dev_map;
|
||||
|
|
@ -266,9 +268,57 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
|
|||
return tt;
|
||||
}
|
||||
|
||||
static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
|
||||
int lun_end)
|
||||
{
|
||||
if (lun_begin > lun_end || lun_end >= geo->all_luns) {
|
||||
pr_err("nvm: lun out of bound (%u:%u > %u)\n",
|
||||
lun_begin, lun_end, geo->all_luns - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __nvm_config_simple(struct nvm_dev *dev,
|
||||
struct nvm_ioctl_create_simple *s)
|
||||
{
|
||||
struct nvm_geo *geo = &dev->geo;
|
||||
|
||||
if (s->lun_begin == -1 && s->lun_end == -1) {
|
||||
s->lun_begin = 0;
|
||||
s->lun_end = geo->all_luns - 1;
|
||||
}
|
||||
|
||||
return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
|
||||
}
|
||||
|
||||
static int __nvm_config_extended(struct nvm_dev *dev,
|
||||
struct nvm_ioctl_create_extended *e)
|
||||
{
|
||||
struct nvm_geo *geo = &dev->geo;
|
||||
|
||||
if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
|
||||
e->lun_begin = 0;
|
||||
e->lun_end = dev->geo.all_luns - 1;
|
||||
}
|
||||
|
||||
/* op not set falls into target's default */
|
||||
if (e->op == 0xFFFF)
|
||||
e->op = NVM_TARGET_DEFAULT_OP;
|
||||
|
||||
if (e->op < NVM_TARGET_MIN_OP ||
|
||||
e->op > NVM_TARGET_MAX_OP) {
|
||||
pr_err("nvm: invalid over provisioning value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
|
||||
}
|
||||
|
||||
static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
|
||||
{
|
||||
struct nvm_ioctl_create_simple *s = &create->conf.s;
|
||||
struct nvm_ioctl_create_extended e;
|
||||
struct request_queue *tqueue;
|
||||
struct gendisk *tdisk;
|
||||
struct nvm_tgt_type *tt;
|
||||
|
|
@ -277,6 +327,28 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
|
|||
void *targetdata;
|
||||
int ret;
|
||||
|
||||
switch (create->conf.type) {
|
||||
case NVM_CONFIG_TYPE_SIMPLE:
|
||||
ret = __nvm_config_simple(dev, &create->conf.s);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
e.lun_begin = create->conf.s.lun_begin;
|
||||
e.lun_end = create->conf.s.lun_end;
|
||||
e.op = NVM_TARGET_DEFAULT_OP;
|
||||
break;
|
||||
case NVM_CONFIG_TYPE_EXTENDED:
|
||||
ret = __nvm_config_extended(dev, &create->conf.e);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
e = create->conf.e;
|
||||
break;
|
||||
default:
|
||||
pr_err("nvm: config type not valid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tt = nvm_find_target_type(create->tgttype);
|
||||
if (!tt) {
|
||||
pr_err("nvm: target type %s not found\n", create->tgttype);
|
||||
|
|
@ -289,7 +361,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = nvm_reserve_luns(dev, s->lun_begin, s->lun_end);
|
||||
ret = nvm_reserve_luns(dev, e.lun_begin, e.lun_end);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -299,7 +371,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
|
|||
goto err_reserve;
|
||||
}
|
||||
|
||||
tgt_dev = nvm_create_tgt_dev(dev, s->lun_begin, s->lun_end);
|
||||
tgt_dev = nvm_create_tgt_dev(dev, e.lun_begin, e.lun_end, e.op);
|
||||
if (!tgt_dev) {
|
||||
pr_err("nvm: could not create target device\n");
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -369,7 +441,7 @@ err_dev:
|
|||
err_t:
|
||||
kfree(t);
|
||||
err_reserve:
|
||||
nvm_release_luns_err(dev, s->lun_begin, s->lun_end);
|
||||
nvm_release_luns_err(dev, e.lun_begin, e.lun_end);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -949,7 +1021,6 @@ EXPORT_SYMBOL(nvm_unregister);
|
|||
static int __nvm_configure_create(struct nvm_ioctl_create *create)
|
||||
{
|
||||
struct nvm_dev *dev;
|
||||
struct nvm_ioctl_create_simple *s;
|
||||
|
||||
down_write(&nvm_lock);
|
||||
dev = nvm_find_nvm_dev(create->dev);
|
||||
|
|
@ -960,23 +1031,6 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (create->conf.type != NVM_CONFIG_TYPE_SIMPLE) {
|
||||
pr_err("nvm: config type not valid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
s = &create->conf.s;
|
||||
|
||||
if (s->lun_begin == -1 && s->lun_end == -1) {
|
||||
s->lun_begin = 0;
|
||||
s->lun_end = dev->geo.all_luns - 1;
|
||||
}
|
||||
|
||||
if (s->lun_begin > s->lun_end || s->lun_end >= dev->geo.all_luns) {
|
||||
pr_err("nvm: lun out of bound (%u:%u > %u)\n",
|
||||
s->lun_begin, s->lun_end, dev->geo.all_luns - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return nvm_create_tgt(dev, create);
|
||||
}
|
||||
|
||||
|
|
@ -1076,6 +1130,12 @@ static long nvm_ioctl_dev_create(struct file *file, void __user *arg)
|
|||
if (copy_from_user(&create, arg, sizeof(struct nvm_ioctl_create)))
|
||||
return -EFAULT;
|
||||
|
||||
if (create.conf.type == NVM_CONFIG_TYPE_EXTENDED &&
|
||||
create.conf.e.rsv != 0) {
|
||||
pr_err("nvm: reserved config field in use\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
create.dev[DISK_NAME_LEN - 1] = '\0';
|
||||
create.tgttype[NVM_TTYPE_NAME_MAX - 1] = '\0';
|
||||
create.tgtname[DISK_NAME_LEN - 1] = '\0';
|
||||
|
|
|
|||
|
|
@ -585,7 +585,10 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
|
|||
sector_t provisioned;
|
||||
int sec_meta, blk_meta;
|
||||
|
||||
pblk->op = 20;
|
||||
if (geo->op == NVM_TARGET_DEFAULT_OP)
|
||||
pblk->op = PBLK_DEFAULT_OP;
|
||||
else
|
||||
pblk->op = geo->op;
|
||||
|
||||
provisioned = nr_free_blks;
|
||||
provisioned *= (100 - pblk->op);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@
|
|||
/* Static pool sizes */
|
||||
#define PBLK_GEN_WS_POOL_SIZE (2)
|
||||
|
||||
#define PBLK_DEFAULT_OP (11)
|
||||
|
||||
enum {
|
||||
PBLK_READ = READ,
|
||||
PBLK_WRITE = WRITE,/* Write from write buffer */
|
||||
|
|
|
|||
Loading…
Reference in a new issue