[RHEL7,COMMIT] ploop: kaio: Close race between truncate thread and grow

Submitted by Kirill Tkhai on Feb. 19, 2020, 3:06 p.m.

Details

Message ID 202002191506.01JF6v2t370550@localhost.localdomain
State New
Series "ploop: kaio: Close race between truncate thread and grow"
Headers show

Commit Message

Kirill Tkhai Feb. 19, 2020, 3:06 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.3
------>
commit 49dca51211aa459d3b5f9f58493ff3bb3d0106fb
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Wed Feb 19 15:06:57 2020 +0000

    ploop: kaio: Close race between truncate thread and grow
    
    .submit_alloc may queue prealloc_preq and set io->prealloc_size.
    Despite .alloc is called under quiesce state, previously submitted
    prealloc_preq may be handled by truncate thread. After quiesce state
    is released, ploop thread updates io->prealloced_size, but inode
    size is less, since kaio_alloc_sync() truncates image under them.
    Fix that.
    
    https://jira.sw.ru/browse/PSBM-101533
    
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/io_kaio.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/io_kaio.c b/drivers/block/ploop/io_kaio.c
index 9ed448b..51ee627 100644
--- a/drivers/block/ploop/io_kaio.c
+++ b/drivers/block/ploop/io_kaio.c
@@ -890,10 +890,26 @@  static int kaio_sync_read_many(struct ploop_io *io, struct page *pages[],
 
 static int kaio_alloc_sync(struct ploop_io * io, loff_t pos, loff_t len)
 {
-	int err = __kaio_truncate(io, io->files.file, pos + len);
+	struct ploop_device *plo = io->plo;
+	loff_t size = pos + len;
+	int err = 0;
+	u32 a_h;
 
-	if (!err)
-		io->alloc_head = (pos + len) >> (io->plo->cluster_log + 9);
+	a_h = size >> (plo->cluster_log + 9);
+
+	/* Close race with truncate thread */
+	if (io->prealloc_preq && size < io->prealloc_preq->prealloc_size)
+		size = io->prealloc_preq->prealloc_size;
+	if (size < io->prealloced_size)
+		size = io->prealloced_size;
+
+	if (size > i_size_read(io->files.inode))
+		err = __kaio_truncate(io, io->files.file, size);
+
+	if (!err) {
+		WARN_ON(io->alloc_head > a_h);
+		io->alloc_head = a_h;
+	}
 
 	return err;
 }