[Devel] [PATCH rh7] ploop: fix race on prealloc request

Maxim Patlasov MPatlasov at openvz.org
Wed Aug 5 17:02:23 PDT 2015


kaio_submit_alloc() sometimes piggybacks ploop request with additional work:
set preq->prealloc_size, pass preq to fsync_thread, perform preallocation
there, get it back to kaio_submit_alloc(), move preallocation from
preq->prealloc_size to io->prealloced_size.

The problem happens when such a request does not get back to kaio_submit_alloc.
For example, it may happen if ploop shrink or compact is in progress: by the
time the request is re-scheduled after preallocation, free blocks emerges,
and ploop_entry_request() use one of them calling kaio_submit intead of
kaio_submit_alloc.

To solve this case and other similar ones, the patch moves the code
transferring preq->prealloc_size to ploop_req_state_process(). Now, this
transfer will be done independently on how ploop state machine decides to
handle that preq.

https://jira.sw.ru/browse/PSBM-35095
---
 drivers/block/ploop/dev.c     |   13 +++++++++++++
 drivers/block/ploop/io_kaio.c |    9 +--------
 2 files changed, 14 insertions(+), 8 deletions(-)
-------------- next part --------------
kaio_submit_alloc() sometimes piggybacks ploop request with additional work:
set preq->prealloc_size, pass preq to fsync_thread, perform preallocation
there, get it back to kaio_submit_alloc(), move preallocation from
preq->prealloc_size to io->prealloced_size.

The problem happens when such a request does not get back to kaio_submit_alloc.
For example, it may happen if ploop shrink or compact is in progress: by the
time the request is re-scheduled after preallocation, free blocks emerges,
and ploop_entry_request() use one of them calling kaio_submit intead of
kaio_submit_alloc.

To solve this case and other similar ones, the patch moves the code
transferring preq->prealloc_size to ploop_req_state_process(). Now, this
transfer will be done independently on how ploop state machine decides to
handle that preq.

https://jira.sw.ru/browse/PSBM-35095
---
 drivers/block/ploop/dev.c     |   13 +++++++++++++
 drivers/block/ploop/io_kaio.c |    9 +--------
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 30eb8a7..97e75a7 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -2275,6 +2275,19 @@ static void ploop_req_state_process(struct ploop_request * preq)
 			ploop_tracker_notify(plo, sec);
 	}
 
+	/* trick: preq->prealloc_size is actually new pos of eof */
+	if (unlikely(preq->prealloc_size && !preq->error)) {
+		struct ploop_io *io = &ploop_top_delta(plo)->io;
+		int log = preq->plo->cluster_log + 9;
+
+		BUG_ON(preq != io->prealloc_preq);
+		io->prealloc_preq = NULL;
+
+		io->prealloced_size = preq->prealloc_size -
+				      ((loff_t)io->alloc_head << log);
+		preq->prealloc_size = 0; /* only for sanity */
+	}
+
 restart:
 	__TRACE("ST %p %u %lu\n", preq, preq->req_cluster, preq->eng_state);
 	switch (preq->eng_state) {
diff --git a/drivers/block/ploop/io_kaio.c b/drivers/block/ploop/io_kaio.c
index ccdf1f4..db900a3 100644
--- a/drivers/block/ploop/io_kaio.c
+++ b/drivers/block/ploop/io_kaio.c
@@ -460,14 +460,7 @@ kaio_submit_alloc(struct ploop_io *io, struct ploop_request * preq,
 		return;
 	}
 
-	/* trick: preq->prealloc_size is actually new pos of eof */
-	if (unlikely(preq->prealloc_size)) {
-		BUG_ON(preq != io->prealloc_preq);
-		io->prealloc_preq = NULL;
-
-		io->prealloced_size = preq->prealloc_size - ((loff_t)iblk << log);
-		preq->prealloc_size = 0; /* only for sanity */
-	}
+	BUG_ON(preq->prealloc_size);
 
 	if (unlikely(io->prealloced_size < clu_siz)) {
 		if (!io->prealloc_preq) {


More information about the Devel mailing list