[Devel] [PATCH RHEL7 COMMIT] ploop: fix direct_io prealloc checks

Konstantin Khorenko khorenko at virtuozzo.com
Wed Mar 16 06:17:26 PDT 2016


The commit is pushed to "branch-rh7-3.10.0-327.10.1.vz7.12.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.10.1.vz7.12.2
------>
commit 635c56541370c23dc2741c28375e3a8c5e3c1410
Author: Maxim Patlasov <mpatlasov at virtuozzo.com>
Date:   Wed Mar 16 17:17:26 2016 +0400

    ploop: fix direct_io prealloc checks
    
    Long time ago, when ploop used FALLOC_FL_KEEP_SIZE, the logic of
    updating io->prealloced_size was implemented correctly:
    
    1) Calculate [pos, end_pos) -- a fragment of image file we're going to
       write to.
    
    2) If [pos, end_pos) is beyond end of file (i.e. end_pos > i_size), let's
       either simply use preallocated space:
    
    	io->prealloced_size -= clu_siz;
    
       or firstly prealloc more space and then use the space:
    
    	fallocate(file, mode, pos, prealloc);
    	io->prealloced_size -= clu_siz;
    
    Now, when ploop doesn't use FALLOC_FL_KEEP_SIZE, the logic above doesn't
    work as expected because after prealloc, i_size is extended and the condition
    "end_pos > i_size" is false. Hence, a lot of writes to preallocated space
    come without "io->prealloced_size -= clu_siz;". And, when all preallocated
    space is logically exhausted, io->prealloced_size is still not zero. Then
    ploop skips fallocate() and goes to pagecache_write_begin() stuff.
    
    https://jira.sw.ru/browse/PSBM-22381
    
    Signed-off-by: Maxim Patlasov <mpatlasov at virtuozzo.com>
    Acked-by: Dmitry Monakhov <dmonakhov at virtuozzo.com>
---
 drivers/block/ploop/io_direct.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index cfd7882..3678d5b 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -69,7 +69,7 @@ struct bio_list_walk
 
 static int cached_submit(struct ploop_io *io, iblock_t iblk,
 	      struct ploop_request * preq,
-	      struct bio_list * sbl, unsigned int size);
+	      struct bio_list * sbl, unsigned int size, bool use_prealloc);
 
 static void
 dio_submit(struct ploop_io *io, struct ploop_request * preq,
@@ -268,7 +268,7 @@ write_unint:
 	ploop_add_lockout(preq, 0);
 	spin_unlock_irq(&preq->plo->lock);
 
-	err = cached_submit(io, iblk, preq, sbl, size);
+	err = cached_submit(io, iblk, preq, sbl, size, false);
 	goto out;
 
 write_unint_fail:
@@ -362,7 +362,7 @@ static inline void bzero_page(struct page *page)
 
 static int
 cached_submit(struct ploop_io *io, iblock_t iblk, struct ploop_request * preq,
-	      struct bio_list * sbl, unsigned int size)
+	      struct bio_list * sbl, unsigned int size, bool use_prealloc)
 {
 	struct ploop_device * plo = preq->plo;
 	int err = 0;
@@ -370,14 +370,16 @@ cached_submit(struct ploop_io *io, iblock_t iblk, struct ploop_request * preq,
 	loff_t clu_siz = 1 << (plo->cluster_log + 9);
 	struct bio_iter biter;
 	loff_t new_size;
+	loff_t used_pos;
 
 	trace_cached_submit(preq);
 
 	pos = (loff_t)iblk << (plo->cluster_log + 9);
 	end_pos = pos + clu_siz;
+	used_pos = (io->alloc_head - 1) << (io->plo->cluster_log + 9);
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)
-	if (end_pos > i_size_read(io->files.inode) &&
+	if (use_prealloc && end_pos > used_pos &&
 	    io->files.file->f_op->fallocate &&
 	    io->files.flags & EXT4_EXTENTS_FL) {
 		if (unlikely(io->prealloced_size < clu_siz)) {
@@ -701,7 +703,7 @@ dio_submit_alloc(struct ploop_io *io, struct ploop_request * preq,
 		return;
 	}
 
-	err = cached_submit(io, iblk, preq, sbl, size);
+	err = cached_submit(io, iblk, preq, sbl, size, true);
 	if (err) {
 		if (err == -ENOSPC)
 			io->alloc_head--;


More information about the Devel mailing list