[RHEL7,COMMIT] ploop: Delay reusing cluster on discard till previous index flushed

Submitted by Konstantin Khorenko on Feb. 27, 2020, 2:41 p.m.

Details

Message ID 202002271441.01REfKxv025518@finist-ce7.sw.ru
State New
Series "ploop: Delay reusing cluster on discard till previous index flushed"
Headers show

Commit Message

Konstantin Khorenko Feb. 27, 2020, 2:41 p.m.
The commit is pushed to "branch-rh7-3.10.0-1062.12.1.vz7.131.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1062.12.1.vz7.131.4
------>
commit c7d428f3a7d83e75899ac97cbac7e2e77640e7cb
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Thu Feb 20 16:09:43 2020 +0300

    ploop: Delay reusing cluster on discard till previous index flushed
    
    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>
    
    v2: WARN_ON added as we don't expect ploop1_add_free_blk() is ever
    called in "maintenance" mode or upon non-discard ploop request.
---
 drivers/block/ploop/fmt_ploop1.c | 6 ++++++
 drivers/block/ploop/map.c        | 9 +++------
 2 files changed, 9 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 806f020f0bb7d..40e24a31689b0 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -865,6 +865,12 @@  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)) {
+		WARN_ON_ONCE(1);
+		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 99b1eb7354691..f6a38e40d8c45 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) {