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

Konstantin Khorenko khorenko at virtuozzo.com
Thu Feb 27 17:41:20 MSK 2020


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 at 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 at 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(-)

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) {


More information about the Devel mailing list