[rh7] ploop: Delay reusing cluster on discard till previous index flushed

Submitted by Kirill Tkhai on Feb. 20, 2020, 1:09 p.m.

Details

Message ID 158220417244.618843.6728792706811237615.stgit@localhost.localdomain
State New
Series "ploop: Delay reusing cluster on discard till previous index flushed"
Headers show

Commit Message

Kirill Tkhai Feb. 20, 2020, 1:09 p.m.
There is a race window, when previous index is not guaranteed
to be zeroed, while we already reuse the cluster it pointed before.
This may results in two indexes point to the same cluster after
node crash.

Fix that by moving cluster into free clusters pool one stage later.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/fmt_ploop1.c |    4 ++++
 drivers/block/ploop/map.c        |    9 +++------
 2 files changed, 7 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 806f020f0bb7..952db7c12cc5 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -865,6 +865,10 @@  static void ploop1_add_free_blk(struct ploop_delta *delta, struct ploop_request
 	if (!delta->holes_bitmap)
 		return;
 
+	if (!(preq->req_rw & REQ_DISCARD) ||
+	    test_bit(PLOOP_REQ_DISCARD, &preq->state))
+		return;
+
 	idx = (preq->req_cluster + PLOOP_MAP_OFFSET) & (INDEX_PER_PAGE - 1);
 	blk = ((map_index_t *)page_address(m->page))[idx];
 
diff --git a/drivers/block/ploop/map.c b/drivers/block/ploop/map.c
index 99b1eb735469..f6a38e40d8c4 100644
--- a/drivers/block/ploop/map.c
+++ b/drivers/block/ploop/map.c
@@ -962,9 +962,6 @@  void ploop_index_update(struct ploop_request * preq)
 
 	copy_index_for_wb(page, m, top_delta->level);
 
-	if (!preq->iblock)
-		top_delta->ops->add_free_blk(top_delta, preq);
-
 	((map_index_t*)page_address(page))[idx] = preq->iblock << ploop_map_log(plo);
 
 	get_page(page);
@@ -1108,6 +1105,9 @@  static void map_wb_complete(struct map_node * m, int err)
 							      list);
 				}
 
+				if (!pr->iblock)
+					top_delta->ops->add_free_blk(top_delta, pr);
+
 				if (m->levels &&  m->levels[idx] != top_delta->level) {
 					spin_lock_irq(&plo->lock);
 					do_levels_update = 1;
@@ -1189,9 +1189,6 @@  static void map_wb_complete(struct map_node * m, int err)
 			preq->sinfo.wi.tpage = page;
 			idx = (preq->req_cluster + PLOOP_MAP_OFFSET) & (INDEX_PER_PAGE - 1);
 
-			if (!preq->iblock)
-				top_delta->ops->add_free_blk(top_delta, preq);
-
 			((map_index_t*)page_address(page))[idx] = preq->iblock << ploop_map_log(plo);
 
 			if (!main_preq) {