Commit d8adaa3b authored by Javier González's avatar Javier González Committed by Jens Axboe

lightnvm: pblk: fix race condition on metadata I/O

In pblk, when a new line is allocated, metadata for the previously
written line is scheduled. This is done through a fixed memory region
that is shared through time and contexts across different lines and
therefore protected by a lock. Unfortunately, this lock is not properly
covering all the metadata used for sharing this memory regions,
resulting in a race condition.

This patch fixes this race condition by protecting this metadata
properly.

Fixes: dd2a4343 ("lightnvm: pblk: sched. metadata on write thread")
Signed-off-by: default avatarJavier González <javier@cnexlabs.com>
Signed-off-by: default avatarMatias Bjørling <mb@lightnvm.io>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 656e33ca
...@@ -417,12 +417,11 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) ...@@ -417,12 +417,11 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id); rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id);
} }
spin_lock(&l_mg->close_lock);
emeta->mem += rq_len; emeta->mem += rq_len;
if (emeta->mem >= lm->emeta_len[0]) { if (emeta->mem >= lm->emeta_len[0])
spin_lock(&l_mg->close_lock);
list_del(&meta_line->list); list_del(&meta_line->list);
spin_unlock(&l_mg->close_lock); spin_unlock(&l_mg->close_lock);
}
pblk_down_page(pblk, rqd->ppa_list, rqd->nr_ppas); pblk_down_page(pblk, rqd->ppa_list, rqd->nr_ppas);
...@@ -491,14 +490,15 @@ static struct pblk_line *pblk_should_submit_meta_io(struct pblk *pblk, ...@@ -491,14 +490,15 @@ static struct pblk_line *pblk_should_submit_meta_io(struct pblk *pblk,
struct pblk_line *meta_line; struct pblk_line *meta_line;
spin_lock(&l_mg->close_lock); spin_lock(&l_mg->close_lock);
retry:
if (list_empty(&l_mg->emeta_list)) { if (list_empty(&l_mg->emeta_list)) {
spin_unlock(&l_mg->close_lock); spin_unlock(&l_mg->close_lock);
return NULL; return NULL;
} }
meta_line = list_first_entry(&l_mg->emeta_list, struct pblk_line, list); meta_line = list_first_entry(&l_mg->emeta_list, struct pblk_line, list);
if (meta_line->emeta->mem >= lm->emeta_len[0]) if (meta_line->emeta->mem >= lm->emeta_len[0]) {
goto retry; spin_unlock(&l_mg->close_lock);
return NULL;
}
spin_unlock(&l_mg->close_lock); spin_unlock(&l_mg->close_lock);
if (!pblk_valid_meta_ppa(pblk, meta_line, data_rqd)) if (!pblk_valid_meta_ppa(pblk, meta_line, data_rqd))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment