summaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm
diff options
context:
space:
mode:
authorJavier González <jg@lightnvm.io>2016-11-28 16:39:05 -0500
committerJens Axboe <axboe@fb.com>2016-11-29 14:12:51 -0500
commit8176117b82e49e043d045f214ba7a892fba6b827 (patch)
tree313d9fbd1d0df7ae9aac03b6f84d01159d3025bf /drivers/lightnvm
parentde93434fcf74d41754a48e45365a5914e00bc0be (diff)
lightnvm: manage lun partitions internally in mm
LUNs are exclusively owned by targets implementing a block device FTL. Doing this reservation requires at the moment a 2-way callback gennvm <-> target. The reason behind this is that LUNs were not assumed to always be exclusively owned by targets. However, this design decision goes against I/O determinism QoS (two targets would mix I/O on the same parallel unit in the device). This patch makes LUN reservation as part of the target creation on the media manager. This makes that LUNs are always exclusively owned by the target instantiated on top of them. LUN stripping and/or sharing should be implemented on the target itself or the layers on top. 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.c62
-rw-r--r--drivers/lightnvm/rrpc.c7
2 files changed, 49 insertions, 20 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 = {
35 .owner = THIS_MODULE, 35 .owner = THIS_MODULE,
36}; 36};
37 37
38static int gen_reserve_luns(struct nvm_dev *dev, struct nvm_target *t,
39 int lun_begin, int lun_end)
40{
41 struct gen_dev *gn = dev->mp;
42 struct nvm_lun *lun;
43 int i;
44
45 for (i = lun_begin; i <= lun_end; i++) {
46 if (test_and_set_bit(i, dev->lun_map)) {
47 pr_err("nvm: lun %d already allocated\n", i);
48 goto err;
49 }
50
51 lun = &gn->luns[i];
52 list_add_tail(&lun->list, &t->lun_list);
53 }
54
55 return 0;
56
57err:
58 while (--i > lun_begin) {
59 lun = &gn->luns[i];
60 clear_bit(i, dev->lun_map);
61 list_del(&lun->list);
62 }
63
64 return -EBUSY;
65}
66
67static void gen_release_luns(struct nvm_dev *dev, struct nvm_target *t)
68{
69 struct nvm_lun *lun, *tmp;
70
71 list_for_each_entry_safe(lun, tmp, &t->lun_list, list) {
72 WARN_ON(!test_and_clear_bit(lun->id, dev->lun_map));
73 list_del(&lun->list);
74 }
75}
76
38static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create) 77static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
39{ 78{
40 struct gen_dev *gn = dev->mp; 79 struct gen_dev *gn = dev->mp;
@@ -64,9 +103,14 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
64 if (!t) 103 if (!t)
65 return -ENOMEM; 104 return -ENOMEM;
66 105
106 INIT_LIST_HEAD(&t->lun_list);
107
108 if (gen_reserve_luns(dev, t, s->lun_begin, s->lun_end))
109 goto err_t;
110
67 tqueue = blk_alloc_queue_node(GFP_KERNEL, dev->q->node); 111 tqueue = blk_alloc_queue_node(GFP_KERNEL, dev->q->node);
68 if (!tqueue) 112 if (!tqueue)
69 goto err_t; 113 goto err_reserve;
70 blk_queue_make_request(tqueue, tt->make_rq); 114 blk_queue_make_request(tqueue, tt->make_rq);
71 115
72 tdisk = alloc_disk(0); 116 tdisk = alloc_disk(0);
@@ -105,6 +149,8 @@ err_init:
105 put_disk(tdisk); 149 put_disk(tdisk);
106err_queue: 150err_queue:
107 blk_cleanup_queue(tqueue); 151 blk_cleanup_queue(tqueue);
152err_reserve:
153 gen_release_luns(dev, t);
108err_t: 154err_t:
109 kfree(t); 155 kfree(t);
110 return -ENOMEM; 156 return -ENOMEM;
@@ -122,6 +168,7 @@ static void __gen_remove_target(struct nvm_target *t)
122 if (tt->exit) 168 if (tt->exit)
123 tt->exit(tdisk->private_data); 169 tt->exit(tdisk->private_data);
124 170
171 gen_release_luns(t->dev, t);
125 put_disk(tdisk); 172 put_disk(tdisk);
126 173
127 list_del(&t->list); 174 list_del(&t->list);
@@ -253,6 +300,7 @@ static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn)
253 INIT_LIST_HEAD(&lun->free_list); 300 INIT_LIST_HEAD(&lun->free_list);
254 INIT_LIST_HEAD(&lun->used_list); 301 INIT_LIST_HEAD(&lun->used_list);
255 INIT_LIST_HEAD(&lun->bb_list); 302 INIT_LIST_HEAD(&lun->bb_list);
303 INIT_LIST_HEAD(&lun->list);
256 304
257 spin_lock_init(&lun->lock); 305 spin_lock_init(&lun->lock);
258 306
@@ -569,16 +617,6 @@ static int gen_erase_blk(struct nvm_dev *dev, struct nvm_block *blk, int flags)
569 return nvm_erase_ppa(dev, &addr, 1, flags); 617 return nvm_erase_ppa(dev, &addr, 1, flags);
570} 618}
571 619
572static int gen_reserve_lun(struct nvm_dev *dev, int lunid)
573{
574 return test_and_set_bit(lunid, dev->lun_map);
575}
576
577static void gen_release_lun(struct nvm_dev *dev, int lunid)
578{
579 WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
580}
581
582static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid) 620static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid)
583{ 621{
584 struct gen_dev *gn = dev->mp; 622 struct gen_dev *gn = dev->mp;
@@ -625,8 +663,6 @@ static struct nvmm_type gen = {
625 .mark_blk = gen_mark_blk, 663 .mark_blk = gen_mark_blk,
626 664
627 .get_lun = gen_get_lun, 665 .get_lun = gen_get_lun,
628 .reserve_lun = gen_reserve_lun,
629 .release_lun = gen_release_lun,
630 .lun_info_print = gen_lun_info_print, 666 .lun_info_print = gen_lun_info_print,
631 667
632 .get_area = gen_get_area, 668 .get_area = gen_get_area,
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 34d2ebf90ed6..88e0d0677b09 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -1126,7 +1126,6 @@ static void rrpc_core_free(struct rrpc *rrpc)
1126 1126
1127static void rrpc_luns_free(struct rrpc *rrpc) 1127static void rrpc_luns_free(struct rrpc *rrpc)
1128{ 1128{
1129 struct nvm_dev *dev = rrpc->dev;
1130 struct nvm_lun *lun; 1129 struct nvm_lun *lun;
1131 struct rrpc_lun *rlun; 1130 struct rrpc_lun *rlun;
1132 int i; 1131 int i;
@@ -1139,7 +1138,6 @@ static void rrpc_luns_free(struct rrpc *rrpc)
1139 lun = rlun->parent; 1138 lun = rlun->parent;
1140 if (!lun) 1139 if (!lun)
1141 break; 1140 break;
1142 dev->mt->release_lun(dev, lun->id);
1143 vfree(rlun->blocks); 1141 vfree(rlun->blocks);
1144 } 1142 }
1145 1143
@@ -1169,11 +1167,6 @@ static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)
1169 int lunid = lun_begin + i; 1167 int lunid = lun_begin + i;
1170 struct nvm_lun *lun; 1168 struct nvm_lun *lun;
1171 1169
1172 if (dev->mt->reserve_lun(dev, lunid)) {
1173 pr_err("rrpc: lun %u is already allocated\n", lunid);
1174 goto err;
1175 }
1176
1177 lun = dev->mt->get_lun(dev, lunid); 1170 lun = dev->mt->get_lun(dev, lunid);
1178 if (!lun) 1171 if (!lun)
1179 goto err; 1172 goto err;