2016-04-13 08:26:14

by Wenwei Tao

[permalink] [raw]
Subject: [PATCH 1/3] lightnvm: calculate rrpc total blocks and sectors up front

Calculate rrpc total blocks and sectors up front, make sense
to use them. For example, we use rrpc->nr_sects to calculate rrpc
area size, but it makes no sense if we don't initialize it up front,
since it would be zero until we finish rrpc luns init.

Signed-off-by: Wenwei Tao <[email protected]>
---
drivers/lightnvm/rrpc.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 3ab6495..c0e303c 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -1207,10 +1207,6 @@ static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)

INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
spin_lock_init(&rlun->lock);
-
- rrpc->total_blocks += dev->blks_per_lun;
- rrpc->nr_sects += dev->sec_per_lun;
-
}

return 0;
@@ -1388,6 +1384,8 @@ static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
INIT_WORK(&rrpc->ws_requeue, rrpc_requeue);

rrpc->nr_luns = lun_end - lun_begin + 1;
+ rrpc->total_blocks = (unsigned long)dev->blks_per_lun * rrpc->nr_luns;
+ rrpc->nr_sects = (unsigned long long)dev->sec_per_lun * rrpc->nr_luns;

/* simple round-robin strategy */
atomic_set(&rrpc->next_lun, -1);
--
1.8.3.1


2016-04-13 08:26:21

by Wenwei Tao

[permalink] [raw]
Subject: [PATCH 2/3] lightnvm: store rrpc soffset in device sector size instead of 512

Since we mainly use soffset in device sector size, we store
that value in rrpc->soffset to reduce doing "(ilog2(dev->sec_size) - 9)".

Signed-off-by: Wenwei Tao <[email protected]>
---
drivers/lightnvm/rrpc.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index c0e303c..3143b98 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -1039,11 +1039,8 @@ static int rrpc_map_init(struct rrpc *rrpc)
{
struct nvm_dev *dev = rrpc->dev;
sector_t i;
- u64 slba;
int ret;

- slba = rrpc->soffset >> (ilog2(dev->sec_size) - 9);
-
rrpc->trans_map = vzalloc(sizeof(struct rrpc_addr) * rrpc->nr_sects);
if (!rrpc->trans_map)
return -ENOMEM;
@@ -1065,8 +1062,8 @@ static int rrpc_map_init(struct rrpc *rrpc)
return 0;

/* Bring up the mapping table from device */
- ret = dev->ops->get_l2p_tbl(dev, slba, rrpc->nr_sects, rrpc_l2p_update,
- rrpc);
+ ret = dev->ops->get_l2p_tbl(dev, rrpc->soffset, rrpc->nr_sects,
+ rrpc_l2p_update, rrpc);
if (ret) {
pr_err("nvm: rrpc: could not read L2P table.\n");
return -EINVAL;
@@ -1220,18 +1217,24 @@ static int rrpc_area_init(struct rrpc *rrpc, sector_t *begin)
struct nvm_dev *dev = rrpc->dev;
struct nvmm_type *mt = dev->mt;
sector_t size = rrpc->nr_sects * dev->sec_size;
+ int ret;

size >>= 9;

- return mt->get_area(dev, begin, size);
+ ret = mt->get_area(dev, begin, size);
+ if (!ret)
+ *begin >>= (ilog2(dev->sec_size) - 9);
+
+ return ret;
}

static void rrpc_area_free(struct rrpc *rrpc)
{
struct nvm_dev *dev = rrpc->dev;
struct nvmm_type *mt = dev->mt;
+ sector_t begin = rrpc->soffset << (ilog2(dev->sec_size) - 9);

- mt->put_area(dev, rrpc->soffset);
+ mt->put_area(dev, begin);
}

static void rrpc_free(struct rrpc *rrpc)
--
1.8.3.1

2016-04-13 08:26:28

by Wenwei Tao

[permalink] [raw]
Subject: [PATCH 3/3] lightnvm: fix address issues related to multi target

In rrpc, some of the address operations are based on
one target assumption, the global values are always
used. Now multi target is available, we should use
relative/global values properly.

In rrpc_l2p_update, we use relative logical address
to deal with trans_map and rev_trans_map, and check
the bound of target's own intead of global device's.

In rrpc_block_map_update, we should use the global
physcical address to compare with the one in trans_map,
since we store the global value in it.

Signed-off-by: Wenwei Tao <[email protected]>
---
drivers/lightnvm/rrpc.c | 39 ++++++++++++++++++---------------------
1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 3143b98..159dc3b 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -116,15 +116,6 @@ static int block_is_full(struct rrpc *rrpc, struct rrpc_block *rblk)
return (rblk->next_page == rrpc->dev->sec_per_blk);
}

-/* Calculate relative addr for the given block, considering instantiated LUNs */
-static u64 block_to_rel_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
-{
- struct nvm_block *blk = rblk->parent;
- int lun_blk = blk->id % (rrpc->dev->blks_per_lun * rrpc->nr_luns);
-
- return lun_blk * rrpc->dev->sec_per_blk;
-}
-
/* Calculate global addr for the given block */
static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
{
@@ -997,24 +988,29 @@ static void rrpc_map_free(struct rrpc *rrpc)
static int rrpc_l2p_update(u64 slba, u32 nlb, __le64 *entries, void *private)
{
struct rrpc *rrpc = (struct rrpc *)private;
- struct nvm_dev *dev = rrpc->dev;
- struct rrpc_addr *addr = rrpc->trans_map + slba;
- struct rrpc_rev_addr *raddr = rrpc->rev_trans_map;
- u64 elba = slba + nlb;
- u64 i;
+ struct rrpc_addr *addr;
+ struct rrpc_rev_addr *raddr;
+ u64 i, elba = slba + nlb - 1;

- if (unlikely(elba > dev->total_secs)) {
+ if (unlikely(slba < rrpc->soffset ||
+ elba > rrpc->soffset + rrpc->nr_sects - 1)) {
pr_err("nvm: L2P data from device is out of bounds!\n");
return -EINVAL;
}

+ slba -= rrpc->soffset;
+ addr = rrpc->trans_map + slba;
+ raddr = rrpc->rev_trans_map;
+
for (i = 0; i < nlb; i++) {
u64 pba = le64_to_cpu(entries[i]);
unsigned int mod;
/* LNVM treats address-spaces as silos, LBA and PBA are
* equally large and zero-indexed.
*/
- if (unlikely(pba >= dev->total_secs && pba != U64_MAX)) {
+ if (unlikely((pba < rrpc->poffset ||
+ pba > rrpc->poffset + rrpc->nr_sects - 1) &&
+ (pba != U64_MAX && pba != 0))) {
pr_err("nvm: L2P data entry is out of bounds!\n");
return -EINVAL;
}
@@ -1289,19 +1285,20 @@ static void rrpc_block_map_update(struct rrpc *rrpc, struct rrpc_block *rblk)
struct nvm_dev *dev = rrpc->dev;
int offset;
struct rrpc_addr *laddr;
- u64 bpaddr, paddr, pladdr;
+ u64 paddr, rpaddr, pladdr;
+
+ paddr = block_to_addr(rrpc, rblk);
+ rpaddr = paddr - rrpc->poffset;

- bpaddr = block_to_rel_addr(rrpc, rblk);
for (offset = 0; offset < dev->sec_per_blk; offset++) {
- paddr = bpaddr + offset;

- pladdr = rrpc->rev_trans_map[paddr].addr;
+ pladdr = rrpc->rev_trans_map[rpaddr + offset].addr;
if (pladdr == ADDR_EMPTY)
continue;

laddr = &rrpc->trans_map[pladdr];

- if (paddr == laddr->addr) {
+ if (paddr + offset == laddr->addr) {
laddr->rblk = rblk;
} else {
set_bit(offset, rblk->invalid_pages);
--
1.8.3.1

2016-04-16 13:29:05

by Matias Bjørling

[permalink] [raw]
Subject: Re: [PATCH 1/3] lightnvm: calculate rrpc total blocks and sectors up front

On 04/13/2016 10:27 AM, Wenwei Tao wrote:
> Calculate rrpc total blocks and sectors up front, make sense
> to use them. For example, we use rrpc->nr_sects to calculate rrpc
> area size, but it makes no sense if we don't initialize it up front,
> since it would be zero until we finish rrpc luns init.
>
> Signed-off-by: Wenwei Tao <[email protected]>
> ---
> drivers/lightnvm/rrpc.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
> index 3ab6495..c0e303c 100644
> --- a/drivers/lightnvm/rrpc.c
> +++ b/drivers/lightnvm/rrpc.c
> @@ -1207,10 +1207,6 @@ static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)
>
> INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
> spin_lock_init(&rlun->lock);
> -
> - rrpc->total_blocks += dev->blks_per_lun;
> - rrpc->nr_sects += dev->sec_per_lun;
> -
> }
>
> return 0;
> @@ -1388,6 +1384,8 @@ static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
> INIT_WORK(&rrpc->ws_requeue, rrpc_requeue);
>
> rrpc->nr_luns = lun_end - lun_begin + 1;
> + rrpc->total_blocks = (unsigned long)dev->blks_per_lun * rrpc->nr_luns;
> + rrpc->nr_sects = (unsigned long long)dev->sec_per_lun * rrpc->nr_luns;
>
> /* simple round-robin strategy */
> atomic_set(&rrpc->next_lun, -1);
>

Thanks Wenwei. Applied for 4.7.

2016-04-16 14:03:05

by Matias Bjørling

[permalink] [raw]
Subject: Re: [PATCH 2/3] lightnvm: store rrpc soffset in device sector size instead of 512

On 04/13/2016 10:27 AM, Wenwei Tao wrote:
> Since we mainly use soffset in device sector size, we store
> that value in rrpc->soffset to reduce doing "(ilog2(dev->sec_size) - 9)".
>
> Signed-off-by: Wenwei Tao <[email protected]>
> ---
> drivers/lightnvm/rrpc.c | 17 ++++++++++-------
> 1 file changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
> index c0e303c..3143b98 100644
> --- a/drivers/lightnvm/rrpc.c
> +++ b/drivers/lightnvm/rrpc.c
> @@ -1039,11 +1039,8 @@ static int rrpc_map_init(struct rrpc *rrpc)
> {
> struct nvm_dev *dev = rrpc->dev;
> sector_t i;
> - u64 slba;
> int ret;
>
> - slba = rrpc->soffset >> (ilog2(dev->sec_size) - 9);
> -
> rrpc->trans_map = vzalloc(sizeof(struct rrpc_addr) * rrpc->nr_sects);
> if (!rrpc->trans_map)
> return -ENOMEM;
> @@ -1065,8 +1062,8 @@ static int rrpc_map_init(struct rrpc *rrpc)
> return 0;
>
> /* Bring up the mapping table from device */
> - ret = dev->ops->get_l2p_tbl(dev, slba, rrpc->nr_sects, rrpc_l2p_update,
> - rrpc);
> + ret = dev->ops->get_l2p_tbl(dev, rrpc->soffset, rrpc->nr_sects,
> + rrpc_l2p_update, rrpc);
> if (ret) {
> pr_err("nvm: rrpc: could not read L2P table.\n");
> return -EINVAL;
> @@ -1220,18 +1217,24 @@ static int rrpc_area_init(struct rrpc *rrpc, sector_t *begin)
> struct nvm_dev *dev = rrpc->dev;
> struct nvmm_type *mt = dev->mt;
> sector_t size = rrpc->nr_sects * dev->sec_size;
> + int ret;
>
> size >>= 9;
>
> - return mt->get_area(dev, begin, size);
> + ret = mt->get_area(dev, begin, size);
> + if (!ret)
> + *begin >>= (ilog2(dev->sec_size) - 9);
> +
> + return ret;
> }
>
> static void rrpc_area_free(struct rrpc *rrpc)
> {
> struct nvm_dev *dev = rrpc->dev;
> struct nvmm_type *mt = dev->mt;
> + sector_t begin = rrpc->soffset << (ilog2(dev->sec_size) - 9);
>
> - mt->put_area(dev, rrpc->soffset);
> + mt->put_area(dev, begin);
> }
>
> static void rrpc_free(struct rrpc *rrpc)
>

Thanks. Applied for 4.7.