[Devel] [PATCH RHEL7 COMMIT] ploop: Fix race between .prepare_merge and .submit_alloc

Konstantin Khorenko khorenko at virtuozzo.com
Mon Apr 1 15:00:12 MSK 2019


The commit is pushed to "branch-rh7-3.10.0-957.10.1.vz7.85.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.10.1.vz7.85.7
------>
commit 82c8b74a4a99d705be295da09d7fa578f85dbef5
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date:   Fri Mar 29 11:47:41 2019 +0300

    ploop: Fix race between .prepare_merge and .submit_alloc
    
    submit_alloc may change alloc_head in parallel,
    and this may lead to data corruption, when we
    read inode size before submit_alloc and update
    the size after submit_alloc.
    
    Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 drivers/block/ploop/dev.c        | 5 +++++
 drivers/block/ploop/fmt_ploop1.c | 4 ++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 1d2167552b26..131ec72b1a1e 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -3782,6 +3782,11 @@ static void ploop_merge_cleanup(struct ploop_device * plo,
 	ploop_relax(plo);
 }
 
+/*
+ * Calls format and io callbacks. Should not be called
+ * in quiesce state, since it may enter quiesce state
+ * itself (in fmt_prepare_merge callback).
+ */
 static int ploop_prepare_merge(struct ploop_delta *next,
 			       struct ploop_snapdata *sd)
 {
diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 4a4aa6bf7ae2..59ba493db9ec 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -379,6 +379,7 @@ ploop1_prepare_merge(struct ploop_delta * delta, struct ploop_snapdata * sd)
 	int err;
 	struct ploop_pvd_header *vh;
 	struct ploop1_private * ph = delta->priv;
+	struct ploop_device *plo = delta->plo;
 
 	vh = (struct ploop_pvd_header *)page_address(ph->dyn_page);
 
@@ -389,9 +390,12 @@ ploop1_prepare_merge(struct ploop_delta * delta, struct ploop_snapdata * sd)
 	if (pvd_header_is_disk_in_use(vh))
 		return -EBUSY;
 
+	/* Close race with submit_alloc */
+	ploop_quiesce(plo);
 	ph->alloc_head = delta->io.ops->i_size_read(&delta->io) >>
 			 (delta->io.plo->cluster_log + 9);
 	delta->io.alloc_head = ph->alloc_head;
+	ploop_relax(plo);
 
 	return 0;
 }



More information about the Devel mailing list