The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear 
at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.30
------>
commit a754359e6e84db055af0ef1bf69e42a75ea82f64
Author: Kirill Tkhai <[email protected]>
Date:   Mon May 17 19:05:02 2021 +0300

    ploop: Switch to blk-mq
    
    It will merge bios for us.
    
    Signed-off-by: Kirill Tkhai <[email protected]>
    
    =====================
    Patchset description:
    
    dm-ploop: Kill loop
    
    Intermediate patches can't be base for bisect.
    
    In scope of https://jira.sw.ru/browse/PSBM-123654
    
    Signed-off-by: Kirill Tkhai <[email protected]>
---
 drivers/md/dm-ploop-map.c    | 127 +++++++++++++++++++++++++++++++++----------
 drivers/md/dm-ploop-target.c |   5 +-
 drivers/md/dm-ploop.h        |  21 ++++++-
 3 files changed, 121 insertions(+), 32 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 2e9cc5f5813f..72df8e64140a 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -5,6 +5,7 @@
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/uio.h>
+#include <linux/blk-mq.h>
 #include <uapi/linux/falloc.h>
 #include "dm-ploop.h"
 
@@ -85,9 +86,10 @@ static void ploop_index_wb_init(struct ploop_index_wb *piwb, 
struct ploop *ploop
        piwb->type = PIWB_TYPE_ALLOC;
 }
 
-static void init_pio(struct ploop *ploop, struct pio *pio)
+static void init_pio(struct ploop *ploop, unsigned int bi_op, struct pio *pio)
 {
        pio->ploop = ploop;
+       pio->bi_opf = bi_op;
        pio->action = PLOOP_END_IO_NONE;
        pio->ref_index = PLOOP_REF_INDEX_INVALID;
        pio->bi_status = BLK_STS_OK;
@@ -127,17 +129,22 @@ static int ploop_pio_cluster(struct ploop *ploop, struct 
pio *pio,
        return 0;
 }
 
-static void call_bio_endio(struct pio *pio, void *data, blk_status_t bi_status)
+static void prq_endio(struct pio *pio, void *prq_ptr, blk_status_t bi_status)
 {
-       struct bio *bio = data;
+        struct ploop_rq *prq = prq_ptr;
+        struct request *rq = prq->rq;
        int ret;
 
        ret = ploop_endio(pio->ploop, pio);
 
        if (bi_status)
-               bio->bi_status = bi_status;
-       if (ret == DM_ENDIO_DONE)
-               bio_endio(bio);
+               dm_request_set_error(rq, bi_status);
+
+       if (ret == DM_ENDIO_DONE) {
+               if (prq->bvec)
+                       kfree(prq->bvec);
+               blk_mq_complete_request(rq);
+       }
 }
 
 void pio_endio(struct pio *pio)
@@ -1109,7 +1116,7 @@ int submit_cluster_cow(struct ploop *ploop, unsigned int 
level,
        pio = alloc_pio_with_pages(ploop);
        if (!pio)
                goto err;
-       init_pio(ploop, pio);
+       init_pio(ploop, REQ_OP_READ, pio);
 
        cow = kmem_cache_alloc(cow_cache, GFP_NOIO);
        if (!cow)
@@ -1126,7 +1133,7 @@ int submit_cluster_cow(struct ploop *ploop, unsigned int 
level,
        pio->endio_cb = ploop_cow_endio;
        pio->endio_cb_data = cow;
 
-       init_pio(ploop, &cow->hook);
+       init_pio(ploop, REQ_OP_WRITE, &cow->hook);
        add_cluster_lk(ploop, &cow->hook, cluster);
 
        /* Stage #0: read secondary delta full cluster */
@@ -1646,45 +1653,107 @@ void do_ploop_fsync_work(struct work_struct *ws)
        }
 }
 
-/*
- * ploop_map() tries to map bio to origins or delays it.
- * It never modifies ploop->bat_entries and other cached
- * metadata: this should be made in do_ploop_work() only.
- */
-int ploop_map(struct dm_target *ti, struct bio *bio)
+static void init_prq(struct ploop_rq *prq, struct request *rq)
 {
-       struct pio *pio = bio_to_endio_hook(bio);
-       struct ploop *ploop = ti->private;
-       unsigned int cluster;
-       unsigned long flags;
+       prq->rq = rq;
+       prq->bvec = NULL;
+}
 
-       init_pio(ploop, pio);
+static noinline struct bio_vec *create_bvec_from_rq(struct request *rq)
+{
+       struct bio_vec bv, *bvec, *tmp;
+       struct req_iterator rq_iter;
+       unsigned int nr_bvec = 0;
 
-       pio->bi_iter = bio->bi_iter;
-       pio->bi_io_vec = bio->bi_io_vec;
-       pio->bi_opf = bio->bi_opf;
-       pio->endio_cb = call_bio_endio;
-       pio->endio_cb_data = bio;
+       rq_for_each_bvec(bv, rq, rq_iter)
+               nr_bvec++;
+
+       bvec = kmalloc_array(nr_bvec, sizeof(struct bio_vec),
+                            GFP_NOIO);
+       if (!bvec)
+               goto out;
+
+       tmp = bvec;
+       rq_for_each_bvec(bv, rq, rq_iter) {
+               *tmp = bv;
+               tmp++;
+       }
+out:
+       return bvec;
+}
+
+static noinline void submit_pio(struct ploop *ploop, struct pio *pio)
+{
+       unsigned int cluster;
+       unsigned long flags;
 
        if (pio->bi_iter.bi_size) {
                if (ploop_pio_cluster(ploop, pio, &cluster) < 0)
-                       return DM_MAPIO_KILL;
+                       goto kill;
                if (op_is_discard(pio->bi_opf) &&
                    endio_if_unsupported_discard(ploop, pio))
-                       return DM_MAPIO_SUBMITTED;
+                       goto out;
 
                defer_pios(ploop, pio, NULL);
-               return DM_MAPIO_SUBMITTED;
+               goto out;
        }
 
-       if (WARN_ON_ONCE(!op_is_flush(pio->bi_opf)))
-               return DM_MAPIO_KILL;
+       if (WARN_ON_ONCE(pio->bi_opf != REQ_OP_FLUSH))
+               goto kill;
 
        spin_lock_irqsave(&ploop->deferred_lock, flags);
        list_add_tail(&pio->list, &ploop->flush_pios);
        spin_unlock_irqrestore(&ploop->deferred_lock, flags);
        queue_work(ploop->wq, &ploop->fsync_worker);
+out:
+       return;
+kill:
+       pio->bi_status = BLK_STS_RESOURCE;
+       pio_endio(pio);
+}
 
+int ploop_clone_and_map(struct dm_target *ti, struct request *rq,
+                   union map_info *info, struct request **clone)
+{
+       struct ploop *ploop = ti->private;
+       struct bio_vec *bvec = NULL;
+       struct ploop_rq *prq;
+       struct pio *pio;
+
+       prq = map_info_to_prq(info);
+       init_prq(prq, rq);
+
+       pio = map_info_to_pio(info); /* Embedded pio */
+       init_pio(ploop, req_op(rq), pio);
+
+       if (rq->bio != rq->biotail) {
+               if (req_op(rq) == REQ_OP_DISCARD)
+                       goto skip_bvec;
+               /*
+                * Transform a set of bvec arrays related to bios
+                * into a single bvec array (which we can iterate).
+                */
+               bvec = create_bvec_from_rq(rq);
+               if (!bvec)
+                       return DM_MAPIO_KILL;
+               prq->bvec = bvec;
+skip_bvec:
+               pio->bi_iter.bi_sector = blk_rq_pos(rq);
+               pio->bi_iter.bi_size = blk_rq_bytes(rq);
+               pio->bi_iter.bi_idx = 0;
+               pio->bi_iter.bi_bvec_done = 0;
+        } else if (rq->bio) {
+                /* Single bio already provides bvec array */
+               bvec = rq->bio->bi_io_vec;
+
+               pio->bi_iter = rq->bio->bi_iter;
+        } /* else FLUSH */
+
+        pio->bi_io_vec = bvec;
+        pio->endio_cb = prq_endio;
+        pio->endio_cb_data = prq;
+
+       submit_pio(ploop, pio);
        return DM_MAPIO_SUBMITTED;
 }
 
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 29d2636f12c9..2a2d36b51de9 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -349,7 +349,7 @@ static int ploop_ctr(struct dm_target *ti, unsigned int 
argc, char **argv)
        if (ret)
                goto err;
 
-       ti->per_io_data_size = sizeof(struct pio);
+       ti->per_io_data_size = ploop_per_io_data_size();
        ti->num_flush_bios = 1;
        ti->flush_supported = true;
        ti->num_discard_bios = 1;
@@ -422,13 +422,14 @@ static int ploop_preresume(struct dm_target *ti)
 static struct target_type ploop_target = {
        .name = "ploop",
        .version = {1, 0, 0},
+       .features = DM_TARGET_SINGLETON|DM_TARGET_IMMUTABLE,
        .module = THIS_MODULE,
        .ctr = ploop_ctr,
        .dtr = ploop_dtr,
-       .map = ploop_map,
        .message = ploop_message,
        .io_hints = ploop_io_hints,
        .preresume = ploop_preresume,
+       .clone_and_map_rq = ploop_clone_and_map,
        .status = ploop_status,
 };
 
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 1b9a7ed8682c..3e562710194b 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -229,6 +229,11 @@ struct ploop {
        spinlock_t pb_lock;
 };
 
+struct ploop_rq {
+       struct request *rq;
+       struct bio_vec *bvec;
+};
+
 struct pio;
 typedef void (*ploop_endio_t)(struct pio *, void *, blk_status_t);
 
@@ -326,6 +331,19 @@ static inline bool whole_cluster(struct ploop *ploop, 
struct pio *pio)
        return !(end_sector & ((1 << ploop->cluster_log) - 1));
 }
 
+static inline ssize_t ploop_per_io_data_size(void)
+{
+       return sizeof(struct ploop_rq) + sizeof(struct pio);
+}
+static inline struct ploop_rq *map_info_to_prq(union map_info *info)
+{
+       return (void *)info->ptr;
+}
+static inline struct pio *map_info_to_pio(union map_info *info)
+{
+       return (void *)info->ptr + sizeof(struct ploop_rq);
+}
+
 #define BAT_LEVEL_MAX          (U8_MAX - 1)
 static inline u8 top_level(struct ploop *ploop)
 {
@@ -517,7 +535,8 @@ extern void do_ploop_work(struct work_struct *ws);
 extern void do_ploop_fsync_work(struct work_struct *ws);
 extern void process_deferred_cmd(struct ploop *ploop,
                        struct ploop_index_wb *piwb);
-extern int ploop_map(struct dm_target *ti, struct bio *bio);
+extern int ploop_clone_and_map(struct dm_target *ti, struct request *rq,
+                   union map_info *map_context, struct request **clone);
 extern int ploop_inflight_bios_ref_switch(struct ploop *ploop, bool killable);
 extern struct pio *find_lk_of_cluster(struct ploop *ploop, u32 cluster);
 extern void unlink_postponed_backup_endio(struct ploop *ploop,
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to