diff options
author | Javier González <jg@lightnvm.io> | 2017-04-15 14:55:42 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-04-16 12:06:25 -0400 |
commit | edee1bdd66bf0fda46a176bc3ee5c992dbbc466e (patch) | |
tree | e899f7abec10a0cffd5e89883411360efcab8a4f /drivers/lightnvm/core.c | |
parent | b0e0306ce14180baee00cea9be5600eef6750af8 (diff) |
lightnvm: double-clear of dev->lun_map on target init error
The dev->lun_map bits are cleared twice if an target init error occurs.
First in the target clean routine, and then next in the nvm_tgt_create
error function. Make sure that it is only cleared once by extending
nvm_remove_tgt_devi() with a clear bit, such that clearing of bits can
ignored when cleaning up a successful initialized target.
Signed-off-by: Javier González <javier@cnexlabs.com>
Fix style.
Signed-off-by: Matias Bjørling <matias@cnexlabs.com>
Signed-off-by: Matias Bjørling <matias@cnexlabs.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r-- | drivers/lightnvm/core.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index a14c52c24e23..5eea3d5ecc30 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c | |||
@@ -89,7 +89,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin, | |||
89 | WARN_ON(!test_and_clear_bit(i, dev->lun_map)); | 89 | WARN_ON(!test_and_clear_bit(i, dev->lun_map)); |
90 | } | 90 | } |
91 | 91 | ||
92 | static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev) | 92 | static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear) |
93 | { | 93 | { |
94 | struct nvm_dev *dev = tgt_dev->parent; | 94 | struct nvm_dev *dev = tgt_dev->parent; |
95 | struct nvm_dev_map *dev_map = tgt_dev->map; | 95 | struct nvm_dev_map *dev_map = tgt_dev->map; |
@@ -100,11 +100,14 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev) | |||
100 | int *lun_offs = ch_map->lun_offs; | 100 | int *lun_offs = ch_map->lun_offs; |
101 | int ch = i + ch_map->ch_off; | 101 | int ch = i + ch_map->ch_off; |
102 | 102 | ||
103 | for (j = 0; j < ch_map->nr_luns; j++) { | 103 | if (clear) { |
104 | int lun = j + lun_offs[j]; | 104 | for (j = 0; j < ch_map->nr_luns; j++) { |
105 | int lunid = (ch * dev->geo.luns_per_chnl) + lun; | 105 | int lun = j + lun_offs[j]; |
106 | int lunid = (ch * dev->geo.luns_per_chnl) + lun; | ||
106 | 107 | ||
107 | WARN_ON(!test_and_clear_bit(lunid, dev->lun_map)); | 108 | WARN_ON(!test_and_clear_bit(lunid, |
109 | dev->lun_map)); | ||
110 | } | ||
108 | } | 111 | } |
109 | 112 | ||
110 | kfree(ch_map->lun_offs); | 113 | kfree(ch_map->lun_offs); |
@@ -309,7 +312,7 @@ err_init: | |||
309 | err_queue: | 312 | err_queue: |
310 | blk_cleanup_queue(tqueue); | 313 | blk_cleanup_queue(tqueue); |
311 | err_dev: | 314 | err_dev: |
312 | nvm_remove_tgt_dev(tgt_dev); | 315 | nvm_remove_tgt_dev(tgt_dev, 0); |
313 | err_t: | 316 | err_t: |
314 | kfree(t); | 317 | kfree(t); |
315 | err_reserve: | 318 | err_reserve: |
@@ -332,7 +335,7 @@ static void __nvm_remove_target(struct nvm_target *t) | |||
332 | if (tt->exit) | 335 | if (tt->exit) |
333 | tt->exit(tdisk->private_data); | 336 | tt->exit(tdisk->private_data); |
334 | 337 | ||
335 | nvm_remove_tgt_dev(t->dev); | 338 | nvm_remove_tgt_dev(t->dev, 1); |
336 | put_disk(tdisk); | 339 | put_disk(tdisk); |
337 | 340 | ||
338 | list_del(&t->list); | 341 | list_del(&t->list); |