diff options
Diffstat (limited to 'drivers/lightnvm/gennvm.c')
-rw-r--r-- | drivers/lightnvm/gennvm.c | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 3572ebbb50ce..9671e11356be 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c @@ -35,6 +35,45 @@ static const struct block_device_operations gen_fops = { .owner = THIS_MODULE, }; +static int gen_reserve_luns(struct nvm_dev *dev, struct nvm_target *t, + int lun_begin, int lun_end) +{ + struct gen_dev *gn = dev->mp; + struct nvm_lun *lun; + int i; + + for (i = lun_begin; i <= lun_end; i++) { + if (test_and_set_bit(i, dev->lun_map)) { + pr_err("nvm: lun %d already allocated\n", i); + goto err; + } + + lun = &gn->luns[i]; + list_add_tail(&lun->list, &t->lun_list); + } + + return 0; + +err: + while (--i > lun_begin) { + lun = &gn->luns[i]; + clear_bit(i, dev->lun_map); + list_del(&lun->list); + } + + return -EBUSY; +} + +static void gen_release_luns(struct nvm_dev *dev, struct nvm_target *t) +{ + struct nvm_lun *lun, *tmp; + + list_for_each_entry_safe(lun, tmp, &t->lun_list, list) { + WARN_ON(!test_and_clear_bit(lun->id, dev->lun_map)); + list_del(&lun->list); + } +} + static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create) { struct gen_dev *gn = dev->mp; @@ -64,9 +103,14 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create) if (!t) return -ENOMEM; + INIT_LIST_HEAD(&t->lun_list); + + if (gen_reserve_luns(dev, t, s->lun_begin, s->lun_end)) + goto err_t; + tqueue = blk_alloc_queue_node(GFP_KERNEL, dev->q->node); if (!tqueue) - goto err_t; + goto err_reserve; blk_queue_make_request(tqueue, tt->make_rq); tdisk = alloc_disk(0); @@ -105,6 +149,8 @@ err_init: put_disk(tdisk); err_queue: blk_cleanup_queue(tqueue); +err_reserve: + gen_release_luns(dev, t); err_t: kfree(t); return -ENOMEM; @@ -122,6 +168,7 @@ static void __gen_remove_target(struct nvm_target *t) if (tt->exit) tt->exit(tdisk->private_data); + gen_release_luns(t->dev, t); put_disk(tdisk); list_del(&t->list); @@ -253,6 +300,7 @@ static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn) INIT_LIST_HEAD(&lun->free_list); INIT_LIST_HEAD(&lun->used_list); INIT_LIST_HEAD(&lun->bb_list); + INIT_LIST_HEAD(&lun->list); spin_lock_init(&lun->lock); @@ -569,16 +617,6 @@ static int gen_erase_blk(struct nvm_dev *dev, struct nvm_block *blk, int flags) return nvm_erase_ppa(dev, &addr, 1, flags); } -static int gen_reserve_lun(struct nvm_dev *dev, int lunid) -{ - return test_and_set_bit(lunid, dev->lun_map); -} - -static void gen_release_lun(struct nvm_dev *dev, int lunid) -{ - WARN_ON(!test_and_clear_bit(lunid, dev->lun_map)); -} - static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid) { struct gen_dev *gn = dev->mp; @@ -625,8 +663,6 @@ static struct nvmm_type gen = { .mark_blk = gen_mark_blk, .get_lun = gen_get_lun, - .reserve_lun = gen_reserve_lun, - .release_lun = gen_release_lun, .lun_info_print = gen_lun_info_print, .get_area = gen_get_area, |