[Devel] [PATCH rh7 13/38] ploop: fix a race condition on relocation of blocks
Andrey Smetanin
asmetanin at virtuozzo.com
Fri May 15 09:48:14 PDT 2015
map_release() are not atomic, because it calls atomic_read
and atomic_dec_and_test. Looks like it was designed to be
called under plo->lock.
https://jira.sw.ru/browse/PSBM-23905
Signed-off-by: Andrey Vagin <avagin at openvz.org>
Acked-by: Maxim Patlasov <mpatlasov at parallels.com>
---
drivers/block/ploop/dev.c | 6 ++++++
drivers/block/ploop/map.c | 6 ++++++
2 files changed, 12 insertions(+)
diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 353fb35..e3422d8 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -1471,12 +1471,14 @@ static int prepare_merge_req(struct ploop_request * preq)
return res;
drop_map:
+ spin_lock_irq(&plo->lock);
map_release(preq->trans_map);
preq->trans_map = NULL;
if (preq->map) {
map_release(preq->map);
preq->map = NULL;
}
+ spin_unlock_irq(&plo->lock);
return 1;
}
@@ -1688,8 +1690,10 @@ ploop_entry_reloc_a_req(struct ploop_request *preq, iblock_t *iblk)
if (*clu <= MAP_MAX_IND(preq))
break;
+ spin_lock_irq(&plo->lock);
map_release(preq->map);
preq->map = NULL;
+ spin_unlock_irq(&plo->lock);
}
if (*clu >= plo->map.max_index) {
@@ -1814,8 +1818,10 @@ static int discard_get_index(struct ploop_request *preq)
preq->iblock = 0;
if (preq->map) {
+ spin_lock_irq(&plo->lock);
map_release(preq->map);
preq->map = NULL;
+ spin_unlock_irq(&plo->lock);
}
return 0;
diff --git a/drivers/block/ploop/map.c b/drivers/block/ploop/map.c
index 5f50f81..2e971cd 100644
--- a/drivers/block/ploop/map.c
+++ b/drivers/block/ploop/map.c
@@ -145,6 +145,10 @@ static void flush_lru_buffer(struct ploop_map * map)
map->lru_buffer_ptr = 0;
}
+/*
+ * map_release() must be called under plo-lock, because
+ * The pair atomic_read & atomic_dec_and_test is not atomic.
+ */
void map_release(struct map_node * m)
{
struct ploop_map * map = m->parent;
@@ -1026,9 +1030,11 @@ static void map_wb_complete_post_process(struct ploop_map *map,
}
if (test_bit(PLOOP_REQ_RELOC_S, &preq->state)) {
+ spin_lock_irq(&plo->lock);
del_lockout(preq);
map_release(preq->map);
preq->map = NULL;
+ spin_unlock_irq(&plo->lock);
requeue_req(preq, PLOOP_E_RELOC_COMPLETE);
return;
--
1.9.3
More information about the Devel
mailing list