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 13685f202c8f3addbd3bb128ca2f5767ca6681bb
Author: Maxim Patlasov <mpatla...@virtuozzo.com>
Date:   Wed Mar 16 17:20:50 2016 +0400

    ploop: use FALLOC_FL_CONVERT_UNWRITTEN in io_direct
    
    Patchset description:
    
    ploop: improve the performance of submit_alloc path
    
    Instead of using pagecache_write_begin/pagecache_write_end method, it is
    beneficial to preallocate space, then write data directly to block-device,
    then convert uninitialized extents (ext4) explicitly.
    
    The following series implements:
     - a preparation patch replcacing BLOCK_UNINIT with em->uninit
     - a patch implementing performance improvement
    
    ===
    This patch description:
    
    The patch implements an optimization of submit_alloc path for pio_direct:
    write user data directly to host block-device (accordingly to fiemap info)
    and then use fallocate(FALLOC_FL_CONVERT_UNWRITTEN). This avoids expensive
    pagecache_write_begin/copy/pagecache_write_end mechanism (saves ~750usec
    per megabyte in my experiments). The feature improves performance
    significantly. Before the patch:
    
    # dd if=/dev/zero of=/mnt2/sb-io-test bs=1M count=10k oflag=dsync
    10240+0 records in
    10240+0 records out
    10737418240 bytes (11 GB) copied, 44.2684 s, 243 MB/s
    
    after the patch:
    
    # dd if=/dev/zero of=/mnt2/sb-io-test bs=1M count=10k oflag=dsync
    10240+0 records in
    10240+0 records out
    10737418240 bytes (11 GB) copied, 29.3066 s, 366 MB/s
    
    https://jira.sw.ru/browse/PSBM-22381
    
    Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
    Acked-by: Dmitry Monakhov <dmonak...@virtuozzo.com>
---
 drivers/block/ploop/dev.c       |  7 +++++++
 drivers/block/ploop/io_direct.c | 42 ++++++++++++++++++++++++++++++++++++++---
 include/linux/ploop/ploop.h     |  6 ++++++
 3 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index feb56c7..1da073c 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -2294,7 +2294,14 @@ static void ploop_req_state_process(struct ploop_request 
* preq)
                preq->prealloc_size = 0; /* only for sanity */
        }
 
+       if (test_bit(PLOOP_REQ_POST_SUBMIT, &preq->state)) {
+               preq->eng_io->ops->post_submit(preq->eng_io, preq);
+               clear_bit(PLOOP_REQ_POST_SUBMIT, &preq->state);
+               preq->eng_io = NULL;
+       }
+
 restart:
+       BUG_ON(test_bit(PLOOP_REQ_POST_SUBMIT, &preq->state));
        __TRACE("ST %p %u %lu\n", preq, preq->req_cluster, preq->eng_state);
        switch (preq->eng_state) {
        case PLOOP_E_ENTRY:
diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index 514af4b..d6f0f21 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -359,6 +359,10 @@ static inline void bzero_page(struct page *page)
        kunmap_atomic(kaddr);
 }
 
+static void
+dio_submit_pad(struct ploop_io *io, struct ploop_request * preq,
+              struct bio_list * sbl, unsigned int size,
+              struct extent_map *em);
 
 static int
 cached_submit(struct ploop_io *io, iblock_t iblk, struct ploop_request * preq,
@@ -371,6 +375,8 @@ cached_submit(struct ploop_io *io, iblock_t iblk, struct 
ploop_request * preq,
        struct bio_iter biter;
        loff_t new_size;
        loff_t used_pos;
+       bool may_fallocate = io->files.file->f_op->fallocate &&
+               io->files.flags & EXT4_EXTENTS_FL;
 
        trace_cached_submit(preq);
 
@@ -379,9 +385,7 @@ cached_submit(struct ploop_io *io, iblock_t iblk, struct 
ploop_request * preq,
        used_pos = (io->alloc_head - 1) << (io->plo->cluster_log + 9);
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)
-       if (use_prealloc && end_pos > used_pos &&
-           io->files.file->f_op->fallocate &&
-           io->files.flags & EXT4_EXTENTS_FL) {
+       if (use_prealloc && end_pos > used_pos && may_fallocate) {
                if (unlikely(io->prealloced_size < clu_siz)) {
                        loff_t prealloc = end_pos;
                        if (prealloc > PLOOP_MAX_PREALLOC(plo))
@@ -405,6 +409,21 @@ try_again:
        }
 #endif
 
+       if (may_fallocate) {
+               sector_t sec = (sector_t)iblk << preq->plo->cluster_log;
+               sector_t len = 1 << preq->plo->cluster_log;
+               struct extent_map * em = extent_lookup_create(io, sec, len);
+
+               if (unlikely(IS_ERR(em)))
+                       return PTR_ERR(em);
+
+               preq->iblock = iblk;
+               preq->eng_io = io;
+               set_bit(PLOOP_REQ_POST_SUBMIT, &preq->state);
+               dio_submit_pad(io, preq, sbl, size, em);
+               return 0;
+       }
+
        bio_iter_init(&biter, sbl);
        mutex_lock(&io->files.inode->i_mutex);
 
@@ -480,6 +499,22 @@ try_again:
        return err;
 }
 
+static void
+dio_post_submit(struct ploop_io *io, struct ploop_request * preq)
+{
+       sector_t sec = (sector_t)preq->iblock << preq->plo->cluster_log;
+       loff_t clu_siz = 1 << (preq->plo->cluster_log + 9);
+       int err;
+
+       err = io->files.file->f_op->fallocate(io->files.file,
+                                             FALLOC_FL_CONVERT_UNWRITTEN,
+                                             (loff_t)sec << 9, clu_siz);
+       if (err) {
+               PLOOP_REQ_SET_ERROR(preq, err);
+               set_bit(PLOOP_S_ABORT, &preq->plo->state);
+       }
+}
+
 /* Submit the whole cluster. If preq contains only partial data
  * within the cluster, pad the rest of cluster with zeros.
  */
@@ -1854,6 +1889,7 @@ static struct ploop_io_ops ploop_io_ops_direct =
        .alloc          =       dio_alloc_sync,
        .submit         =       dio_submit,
        .submit_alloc   =       dio_submit_alloc,
+       .post_submit    =       dio_post_submit,
        .disable_merge  =       dio_disable_merge,
        .fastmap        =       dio_fastmap,
        .read_page      =       dio_read_page,
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index b8c7130..c9fb1b0 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -142,6 +142,7 @@ struct ploop_io_ops
                          struct bio_list *sbl, iblock_t iblk, unsigned int 
size);
        void    (*submit_alloc)(struct ploop_io *, struct ploop_request *,
                                struct bio_list *sbl, unsigned int size);
+       void    (*post_submit)(struct ploop_io *, struct ploop_request *);
 
        int     (*disable_merge)(struct ploop_io * io, sector_t isector, 
unsigned int len);
        int     (*fastmap)(struct ploop_io * io, struct bio *orig_bio,
@@ -459,6 +460,7 @@ enum
        PLOOP_REQ_FORCE_FUA,    /*force fua of req write I/O by engine */
        PLOOP_REQ_FORCE_FLUSH,  /*force flush by engine */
        PLOOP_REQ_KAIO_FSYNC,   /*force image fsync by KAIO module */
+       PLOOP_REQ_POST_SUBMIT, /* preq needs post_submit processing */
 };
 
 enum
@@ -561,6 +563,10 @@ struct ploop_request
 
        /* # bytes in tail of image file to prealloc on behalf of this preq */
        loff_t                  prealloc_size;
+
+       /* if the engine starts operation on particular io, let's finish
+        * the operation on the same io (see io.ops->post_submit) */
+       struct ploop_io        *eng_io;
 };
 
 static inline struct ploop_delta * ploop_top_delta(struct ploop_device * plo)
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to