diff options
author | Javier González <javier@javigon.com> | 2018-10-09 07:12:07 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-10-09 10:25:08 -0400 |
commit | 44cdbdc657b23f75736eca3e88b781f009104363 (patch) | |
tree | db6d14e7d352ee04ff6f7ec6ea20a34fdf990d8d | |
parent | 02a1520d56d11982ccc8eab56e4c562fd05d2c86 (diff) |
lightnvm: pblk: fix race on sysfs line state
pblk exposes a sysfs interface that represents its internal state. Part
of this state is the map bitmap for the current open line, which should
be protected by the line lock to avoid a race when freeing the line
metadata. Currently, it is not.
This patch makes sure that the line state is consistent and NULL
bitmap pointers are not dereferenced.
Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/lightnvm/pblk-core.c | 5 | ||||
-rw-r--r-- | drivers/lightnvm/pblk-sysfs.c | 8 |
2 files changed, 10 insertions, 3 deletions
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c index 4045a9b1ee74..6944aac43b01 100644 --- a/drivers/lightnvm/pblk-core.c +++ b/drivers/lightnvm/pblk-core.c | |||
@@ -1611,13 +1611,14 @@ struct pblk_line *pblk_line_replace_data(struct pblk *pblk) | |||
1611 | struct pblk_line *cur, *new = NULL; | 1611 | struct pblk_line *cur, *new = NULL; |
1612 | unsigned int left_seblks; | 1612 | unsigned int left_seblks; |
1613 | 1613 | ||
1614 | cur = l_mg->data_line; | ||
1615 | new = l_mg->data_next; | 1614 | new = l_mg->data_next; |
1616 | if (!new) | 1615 | if (!new) |
1617 | goto out; | 1616 | goto out; |
1618 | l_mg->data_line = new; | ||
1619 | 1617 | ||
1620 | spin_lock(&l_mg->free_lock); | 1618 | spin_lock(&l_mg->free_lock); |
1619 | cur = l_mg->data_line; | ||
1620 | l_mg->data_line = new; | ||
1621 | |||
1621 | pblk_line_setup_metadata(new, l_mg, &pblk->lm); | 1622 | pblk_line_setup_metadata(new, l_mg, &pblk->lm); |
1622 | spin_unlock(&l_mg->free_lock); | 1623 | spin_unlock(&l_mg->free_lock); |
1623 | 1624 | ||
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c index cba83ac43e62..2d2818155aa8 100644 --- a/drivers/lightnvm/pblk-sysfs.c +++ b/drivers/lightnvm/pblk-sysfs.c | |||
@@ -263,8 +263,14 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page) | |||
263 | sec_in_line = l_mg->data_line->sec_in_line; | 263 | sec_in_line = l_mg->data_line->sec_in_line; |
264 | meta_weight = bitmap_weight(&l_mg->meta_bitmap, | 264 | meta_weight = bitmap_weight(&l_mg->meta_bitmap, |
265 | PBLK_DATA_LINES); | 265 | PBLK_DATA_LINES); |
266 | map_weight = bitmap_weight(l_mg->data_line->map_bitmap, | 266 | |
267 | spin_lock(&l_mg->data_line->lock); | ||
268 | if (l_mg->data_line->map_bitmap) | ||
269 | map_weight = bitmap_weight(l_mg->data_line->map_bitmap, | ||
267 | lm->sec_per_line); | 270 | lm->sec_per_line); |
271 | else | ||
272 | map_weight = 0; | ||
273 | spin_unlock(&l_mg->data_line->lock); | ||
268 | } | 274 | } |
269 | spin_unlock(&l_mg->free_lock); | 275 | spin_unlock(&l_mg->free_lock); |
270 | 276 | ||