diff options
| author | Javier González <jg@lightnvm.io> | 2016-11-28 16:39:04 -0500 |
|---|---|---|
| committer | Jens Axboe <axboe@fb.com> | 2016-11-29 14:12:51 -0500 |
| commit | de93434fcf74d41754a48e45365a5914e00bc0be (patch) | |
| tree | 9eae34dfc2ddf9fa9fad129fb78e1f00e90277ae /drivers/lightnvm | |
| parent | 98379a12c54974ee5856dcf81781a5dc845505c3 (diff) | |
lightnvm: remove gen_lun abstraction
The gen_lun abstraction in the generic media manager was conceived on
the assumption that a single target would instantiated on top of it.
This has complicated target design to implement multi-instances. Remove
this abstraction and move its logic to nvm_lun, which manages physical
lun geometry and operations.
Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/lightnvm')
| -rw-r--r-- | drivers/lightnvm/gennvm.c | 85 | ||||
| -rw-r--r-- | drivers/lightnvm/gennvm.h | 16 |
2 files changed, 43 insertions, 58 deletions
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index aee5b722ba63..3572ebbb50ce 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c | |||
| @@ -223,13 +223,13 @@ static void gen_put_area(struct nvm_dev *dev, sector_t begin) | |||
| 223 | static void gen_blocks_free(struct nvm_dev *dev) | 223 | static void gen_blocks_free(struct nvm_dev *dev) |
| 224 | { | 224 | { |
| 225 | struct gen_dev *gn = dev->mp; | 225 | struct gen_dev *gn = dev->mp; |
| 226 | struct gen_lun *lun; | 226 | struct nvm_lun *lun; |
| 227 | int i; | 227 | int i; |
| 228 | 228 | ||
| 229 | gen_for_each_lun(gn, lun, i) { | 229 | gen_for_each_lun(gn, lun, i) { |
| 230 | if (!lun->vlun.blocks) | 230 | if (!lun->blocks) |
| 231 | break; | 231 | break; |
| 232 | vfree(lun->vlun.blocks); | 232 | vfree(lun->blocks); |
| 233 | } | 233 | } |
| 234 | } | 234 | } |
| 235 | 235 | ||
| @@ -242,24 +242,24 @@ static void gen_luns_free(struct nvm_dev *dev) | |||
| 242 | 242 | ||
| 243 | static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn) | 243 | static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn) |
| 244 | { | 244 | { |
| 245 | struct gen_lun *lun; | 245 | struct nvm_lun *lun; |
| 246 | int i; | 246 | int i; |
| 247 | 247 | ||
| 248 | gn->luns = kcalloc(dev->nr_luns, sizeof(struct gen_lun), GFP_KERNEL); | 248 | gn->luns = kcalloc(dev->nr_luns, sizeof(struct nvm_lun), GFP_KERNEL); |
| 249 | if (!gn->luns) | 249 | if (!gn->luns) |
| 250 | return -ENOMEM; | 250 | return -ENOMEM; |
| 251 | 251 | ||
| 252 | gen_for_each_lun(gn, lun, i) { | 252 | gen_for_each_lun(gn, lun, i) { |
| 253 | spin_lock_init(&lun->vlun.lock); | ||
| 254 | INIT_LIST_HEAD(&lun->free_list); | 253 | INIT_LIST_HEAD(&lun->free_list); |
| 255 | INIT_LIST_HEAD(&lun->used_list); | 254 | INIT_LIST_HEAD(&lun->used_list); |
| 256 | INIT_LIST_HEAD(&lun->bb_list); | 255 | INIT_LIST_HEAD(&lun->bb_list); |
| 257 | 256 | ||
| 258 | lun->reserved_blocks = 2; /* for GC only */ | 257 | spin_lock_init(&lun->lock); |
| 259 | lun->vlun.id = i; | 258 | |
| 260 | lun->vlun.lun_id = i % dev->luns_per_chnl; | 259 | lun->id = i; |
| 261 | lun->vlun.chnl_id = i / dev->luns_per_chnl; | 260 | lun->lun_id = i % dev->luns_per_chnl; |
| 262 | lun->vlun.nr_free_blocks = dev->blks_per_lun; | 261 | lun->chnl_id = i / dev->luns_per_chnl; |
| 262 | lun->nr_free_blocks = dev->blks_per_lun; | ||
| 263 | } | 263 | } |
| 264 | return 0; | 264 | return 0; |
| 265 | } | 265 | } |
| @@ -268,7 +268,7 @@ static int gen_block_bb(struct gen_dev *gn, struct ppa_addr ppa, | |||
| 268 | u8 *blks, int nr_blks) | 268 | u8 *blks, int nr_blks) |
| 269 | { | 269 | { |
| 270 | struct nvm_dev *dev = gn->dev; | 270 | struct nvm_dev *dev = gn->dev; |
| 271 | struct gen_lun *lun; | 271 | struct nvm_lun *lun; |
| 272 | struct nvm_block *blk; | 272 | struct nvm_block *blk; |
| 273 | int i; | 273 | int i; |
| 274 | 274 | ||
| @@ -282,9 +282,10 @@ static int gen_block_bb(struct gen_dev *gn, struct ppa_addr ppa, | |||
| 282 | if (blks[i] == NVM_BLK_T_FREE) | 282 | if (blks[i] == NVM_BLK_T_FREE) |
| 283 | continue; | 283 | continue; |
| 284 | 284 | ||
| 285 | blk = &lun->vlun.blocks[i]; | 285 | blk = &lun->blocks[i]; |
| 286 | list_move_tail(&blk->list, &lun->bb_list); | 286 | list_move_tail(&blk->list, &lun->bb_list); |
| 287 | lun->vlun.nr_free_blocks--; | 287 | blk->state = NVM_BLK_ST_BAD; |
| 288 | lun->nr_free_blocks--; | ||
| 288 | } | 289 | } |
| 289 | 290 | ||
| 290 | return 0; | 291 | return 0; |
| @@ -295,7 +296,7 @@ static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private) | |||
| 295 | struct nvm_dev *dev = private; | 296 | struct nvm_dev *dev = private; |
| 296 | struct gen_dev *gn = dev->mp; | 297 | struct gen_dev *gn = dev->mp; |
| 297 | u64 elba = slba + nlb; | 298 | u64 elba = slba + nlb; |
| 298 | struct gen_lun *lun; | 299 | struct nvm_lun *lun; |
| 299 | struct nvm_block *blk; | 300 | struct nvm_block *blk; |
| 300 | u64 i; | 301 | u64 i; |
| 301 | int lun_id; | 302 | int lun_id; |
| @@ -326,7 +327,7 @@ static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private) | |||
| 326 | 327 | ||
| 327 | /* Calculate block offset into lun */ | 328 | /* Calculate block offset into lun */ |
| 328 | pba = pba - (dev->sec_per_lun * lun_id); | 329 | pba = pba - (dev->sec_per_lun * lun_id); |
| 329 | blk = &lun->vlun.blocks[div_u64(pba, dev->sec_per_blk)]; | 330 | blk = &lun->blocks[div_u64(pba, dev->sec_per_blk)]; |
| 330 | 331 | ||
| 331 | if (!blk->state) { | 332 | if (!blk->state) { |
| 332 | /* at this point, we don't know anything about the | 333 | /* at this point, we don't know anything about the |
| @@ -335,7 +336,7 @@ static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private) | |||
| 335 | */ | 336 | */ |
| 336 | list_move_tail(&blk->list, &lun->used_list); | 337 | list_move_tail(&blk->list, &lun->used_list); |
| 337 | blk->state = NVM_BLK_ST_TGT; | 338 | blk->state = NVM_BLK_ST_TGT; |
| 338 | lun->vlun.nr_free_blocks--; | 339 | lun->nr_free_blocks--; |
| 339 | } | 340 | } |
| 340 | } | 341 | } |
| 341 | 342 | ||
| @@ -344,7 +345,7 @@ static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private) | |||
| 344 | 345 | ||
| 345 | static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn) | 346 | static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn) |
| 346 | { | 347 | { |
| 347 | struct gen_lun *lun; | 348 | struct nvm_lun *lun; |
| 348 | struct nvm_block *block; | 349 | struct nvm_block *block; |
| 349 | sector_t lun_iter, blk_iter, cur_block_id = 0; | 350 | sector_t lun_iter, blk_iter, cur_block_id = 0; |
| 350 | int ret, nr_blks; | 351 | int ret, nr_blks; |
| @@ -356,19 +357,19 @@ static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn) | |||
| 356 | return -ENOMEM; | 357 | return -ENOMEM; |
| 357 | 358 | ||
| 358 | gen_for_each_lun(gn, lun, lun_iter) { | 359 | gen_for_each_lun(gn, lun, lun_iter) { |
| 359 | lun->vlun.blocks = vzalloc(sizeof(struct nvm_block) * | 360 | lun->blocks = vzalloc(sizeof(struct nvm_block) * |
| 360 | dev->blks_per_lun); | 361 | dev->blks_per_lun); |
| 361 | if (!lun->vlun.blocks) { | 362 | if (!lun->blocks) { |
| 362 | kfree(blks); | 363 | kfree(blks); |
| 363 | return -ENOMEM; | 364 | return -ENOMEM; |
| 364 | } | 365 | } |
| 365 | 366 | ||
| 366 | for (blk_iter = 0; blk_iter < dev->blks_per_lun; blk_iter++) { | 367 | for (blk_iter = 0; blk_iter < dev->blks_per_lun; blk_iter++) { |
| 367 | block = &lun->vlun.blocks[blk_iter]; | 368 | block = &lun->blocks[blk_iter]; |
| 368 | 369 | ||
| 369 | INIT_LIST_HEAD(&block->list); | 370 | INIT_LIST_HEAD(&block->list); |
| 370 | 371 | ||
| 371 | block->lun = &lun->vlun; | 372 | block->lun = lun; |
| 372 | block->id = cur_block_id++; | 373 | block->id = cur_block_id++; |
| 373 | 374 | ||
| 374 | list_add_tail(&block->list, &lun->free_list); | 375 | list_add_tail(&block->list, &lun->free_list); |
| @@ -378,8 +379,8 @@ static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn) | |||
| 378 | struct ppa_addr ppa; | 379 | struct ppa_addr ppa; |
| 379 | 380 | ||
| 380 | ppa.ppa = 0; | 381 | ppa.ppa = 0; |
| 381 | ppa.g.ch = lun->vlun.chnl_id; | 382 | ppa.g.ch = lun->chnl_id; |
| 382 | ppa.g.lun = lun->vlun.lun_id; | 383 | ppa.g.lun = lun->lun_id; |
| 383 | 384 | ||
| 384 | ret = nvm_get_bb_tbl(dev, ppa, blks); | 385 | ret = nvm_get_bb_tbl(dev, ppa, blks); |
| 385 | if (ret) | 386 | if (ret) |
| @@ -468,41 +469,39 @@ static void gen_unregister(struct nvm_dev *dev) | |||
| 468 | } | 469 | } |
| 469 | 470 | ||
| 470 | static struct nvm_block *gen_get_blk(struct nvm_dev *dev, | 471 | static struct nvm_block *gen_get_blk(struct nvm_dev *dev, |
| 471 | struct nvm_lun *vlun, unsigned long flags) | 472 | struct nvm_lun *lun, unsigned long flags) |
| 472 | { | 473 | { |
| 473 | struct gen_lun *lun = container_of(vlun, struct gen_lun, vlun); | ||
| 474 | struct nvm_block *blk = NULL; | 474 | struct nvm_block *blk = NULL; |
| 475 | int is_gc = flags & NVM_IOTYPE_GC; | 475 | int is_gc = flags & NVM_IOTYPE_GC; |
| 476 | 476 | ||
| 477 | spin_lock(&vlun->lock); | 477 | spin_lock(&lun->lock); |
| 478 | if (list_empty(&lun->free_list)) { | 478 | if (list_empty(&lun->free_list)) { |
| 479 | pr_err_ratelimited("gen: lun %u have no free pages available", | 479 | pr_err_ratelimited("gen: lun %u have no free pages available", |
| 480 | lun->vlun.id); | 480 | lun->id); |
| 481 | goto out; | 481 | goto out; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | if (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks) | 484 | if (!is_gc && lun->nr_free_blocks < lun->reserved_blocks) |
| 485 | goto out; | 485 | goto out; |
| 486 | 486 | ||
| 487 | blk = list_first_entry(&lun->free_list, struct nvm_block, list); | 487 | blk = list_first_entry(&lun->free_list, struct nvm_block, list); |
| 488 | 488 | ||
| 489 | list_move_tail(&blk->list, &lun->used_list); | 489 | list_move_tail(&blk->list, &lun->used_list); |
| 490 | blk->state = NVM_BLK_ST_TGT; | 490 | blk->state = NVM_BLK_ST_TGT; |
| 491 | lun->vlun.nr_free_blocks--; | 491 | lun->nr_free_blocks--; |
| 492 | out: | 492 | out: |
| 493 | spin_unlock(&vlun->lock); | 493 | spin_unlock(&lun->lock); |
| 494 | return blk; | 494 | return blk; |
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | static void gen_put_blk(struct nvm_dev *dev, struct nvm_block *blk) | 497 | static void gen_put_blk(struct nvm_dev *dev, struct nvm_block *blk) |
| 498 | { | 498 | { |
| 499 | struct nvm_lun *vlun = blk->lun; | 499 | struct nvm_lun *lun = blk->lun; |
| 500 | struct gen_lun *lun = container_of(vlun, struct gen_lun, vlun); | ||
| 501 | 500 | ||
| 502 | spin_lock(&vlun->lock); | 501 | spin_lock(&lun->lock); |
| 503 | if (blk->state & NVM_BLK_ST_TGT) { | 502 | if (blk->state & NVM_BLK_ST_TGT) { |
| 504 | list_move_tail(&blk->list, &lun->free_list); | 503 | list_move_tail(&blk->list, &lun->free_list); |
| 505 | lun->vlun.nr_free_blocks++; | 504 | lun->nr_free_blocks++; |
| 506 | blk->state = NVM_BLK_ST_FREE; | 505 | blk->state = NVM_BLK_ST_FREE; |
| 507 | } else if (blk->state & NVM_BLK_ST_BAD) { | 506 | } else if (blk->state & NVM_BLK_ST_BAD) { |
| 508 | list_move_tail(&blk->list, &lun->bb_list); | 507 | list_move_tail(&blk->list, &lun->bb_list); |
| @@ -513,13 +512,13 @@ static void gen_put_blk(struct nvm_dev *dev, struct nvm_block *blk) | |||
| 513 | blk->id, blk->state); | 512 | blk->id, blk->state); |
| 514 | list_move_tail(&blk->list, &lun->bb_list); | 513 | list_move_tail(&blk->list, &lun->bb_list); |
| 515 | } | 514 | } |
| 516 | spin_unlock(&vlun->lock); | 515 | spin_unlock(&lun->lock); |
| 517 | } | 516 | } |
| 518 | 517 | ||
| 519 | static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type) | 518 | static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type) |
| 520 | { | 519 | { |
| 521 | struct gen_dev *gn = dev->mp; | 520 | struct gen_dev *gn = dev->mp; |
| 522 | struct gen_lun *lun; | 521 | struct nvm_lun *lun; |
| 523 | struct nvm_block *blk; | 522 | struct nvm_block *blk; |
| 524 | 523 | ||
| 525 | pr_debug("gen: ppa (ch: %u lun: %u blk: %u pg: %u) -> %u\n", | 524 | pr_debug("gen: ppa (ch: %u lun: %u blk: %u pg: %u) -> %u\n", |
| @@ -537,7 +536,7 @@ static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type) | |||
| 537 | } | 536 | } |
| 538 | 537 | ||
| 539 | lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun]; | 538 | lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun]; |
| 540 | blk = &lun->vlun.blocks[ppa.g.blk]; | 539 | blk = &lun->blocks[ppa.g.blk]; |
| 541 | 540 | ||
| 542 | /* will be moved to bb list on put_blk from target */ | 541 | /* will be moved to bb list on put_blk from target */ |
| 543 | blk->state = type; | 542 | blk->state = type; |
| @@ -587,23 +586,23 @@ static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid) | |||
| 587 | if (unlikely(lunid >= dev->nr_luns)) | 586 | if (unlikely(lunid >= dev->nr_luns)) |
| 588 | return NULL; | 587 | return NULL; |
| 589 | 588 | ||
| 590 | return &gn->luns[lunid].vlun; | 589 | return &gn->luns[lunid]; |
| 591 | } | 590 | } |
| 592 | 591 | ||
| 593 | static void gen_lun_info_print(struct nvm_dev *dev) | 592 | static void gen_lun_info_print(struct nvm_dev *dev) |
| 594 | { | 593 | { |
| 595 | struct gen_dev *gn = dev->mp; | 594 | struct gen_dev *gn = dev->mp; |
| 596 | struct gen_lun *lun; | 595 | struct nvm_lun *lun; |
| 597 | unsigned int i; | 596 | unsigned int i; |
| 598 | 597 | ||
| 599 | 598 | ||
| 600 | gen_for_each_lun(gn, lun, i) { | 599 | gen_for_each_lun(gn, lun, i) { |
| 601 | spin_lock(&lun->vlun.lock); | 600 | spin_lock(&lun->lock); |
| 602 | 601 | ||
| 603 | pr_info("%s: lun%8u\t%u\n", dev->name, i, | 602 | pr_info("%s: lun%8u\t%u\n", dev->name, i, |
| 604 | lun->vlun.nr_free_blocks); | 603 | lun->nr_free_blocks); |
| 605 | 604 | ||
| 606 | spin_unlock(&lun->vlun.lock); | 605 | spin_unlock(&lun->lock); |
| 607 | } | 606 | } |
| 608 | } | 607 | } |
| 609 | 608 | ||
diff --git a/drivers/lightnvm/gennvm.h b/drivers/lightnvm/gennvm.h index 8ecfa817d21d..d167f391fbae 100644 --- a/drivers/lightnvm/gennvm.h +++ b/drivers/lightnvm/gennvm.h | |||
| @@ -20,25 +20,11 @@ | |||
| 20 | 20 | ||
| 21 | #include <linux/lightnvm.h> | 21 | #include <linux/lightnvm.h> |
| 22 | 22 | ||
| 23 | struct gen_lun { | ||
| 24 | struct nvm_lun vlun; | ||
| 25 | |||
| 26 | int reserved_blocks; | ||
| 27 | /* lun block lists */ | ||
| 28 | struct list_head used_list; /* In-use blocks */ | ||
| 29 | struct list_head free_list; /* Not used blocks i.e. released | ||
| 30 | * and ready for use | ||
| 31 | */ | ||
| 32 | struct list_head bb_list; /* Bad blocks. Mutually exclusive with | ||
| 33 | * free_list and used_list | ||
| 34 | */ | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct gen_dev { | 23 | struct gen_dev { |
| 38 | struct nvm_dev *dev; | 24 | struct nvm_dev *dev; |
| 39 | 25 | ||
| 40 | int nr_luns; | 26 | int nr_luns; |
| 41 | struct gen_lun *luns; | 27 | struct nvm_lun *luns; |
| 42 | struct list_head area_list; | 28 | struct list_head area_list; |
| 43 | 29 | ||
| 44 | struct mutex lock; | 30 | struct mutex lock; |
