dm-ploop and dm-qcow2 are request based, so push_backup
also must be request based to switch between them.

Signed-off-by: Kirill Tkhai <[email protected]>
---
 drivers/md/dm-push-backup.c |  124 ++++++++++++++++++++++++-------------------
 1 file changed, 70 insertions(+), 54 deletions(-)

diff --git a/drivers/md/dm-push-backup.c b/drivers/md/dm-push-backup.c
index 77c41680730b..198fe0e55a32 100644
--- a/drivers/md/dm-push-backup.c
+++ b/drivers/md/dm-push-backup.c
@@ -8,11 +8,13 @@
  */
 
 #include "dm.h"
+#include "dm-rq.h"
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/ctype.h>
 #include <linux/dm-io.h>
+#include <linux/blk-mq.h>
 
 
 #define DM_MSG_PREFIX "push-backup"
@@ -25,6 +27,7 @@ static inline struct hlist_head *pb_htable_slot(struct 
hlist_head head[], u32 cl
 }
 
 struct pb_bio {
+       struct request *rq;
        struct hlist_node hlist_node;
        u64 start_clu;
        u64 end_clu;
@@ -62,21 +65,6 @@ struct push_backup {
        struct rw_semaphore ctl_rwsem;
 };
 
-static struct pb_bio *bio_to_pbio(struct bio *bio)
-{
-       return dm_per_bio_data(bio, sizeof(struct pb_bio));
-}
-
-static struct bio *pbio_to_bio(struct pb_bio *pbio)
-{
-       return dm_bio_from_per_bio_data(pbio, sizeof(*pbio));
-}
-
-static inline void remap_to_origin(struct push_backup *pb, struct bio *bio)
-{
-       bio_set_dev(bio, pb->origin_dev->bdev);
-}
-
 static u64 pbio_first_required_for_backup_clu(struct push_backup *pb, struct 
pb_bio *pbio)
 {
        u64 clu;
@@ -99,23 +87,32 @@ static u64 pbio_last_required_for_backup_clu(struct 
push_backup *pb, struct pb_b
        return U64_MAX;
 }
 
-static void calc_bio_clusters(struct push_backup *pb, struct pb_bio *pbio)
+static void init_pb_bio(struct pb_bio *pbio)
+{
+       INIT_HLIST_NODE(&pbio->hlist_node);
+       INIT_LIST_HEAD(&pbio->list);
+}
+
+static void calc_bio_clusters(struct push_backup *pb, struct request *rq,
+                             struct pb_bio *pbio)
 {
-       struct bio *bio = pbio_to_bio(pbio);
-       loff_t off = to_bytes(bio->bi_iter.bi_sector);
+       loff_t off = to_bytes(blk_rq_pos(rq));
 
        pbio->start_clu = off / pb->clu_size;
-       pbio->end_clu = (off + bio->bi_iter.bi_size - 1) / pb->clu_size;
+       pbio->end_clu = (off + blk_rq_bytes(rq) - 1) / pb->clu_size;
 }
 
-static bool setup_if_required_for_backup(struct push_backup *pb, struct pb_bio 
*pbio)
+static bool setup_if_required_for_backup(struct push_backup *pb, struct 
request *rq,
+                                        struct pb_bio *pbio)
 {
        u64 key;
 
-       calc_bio_clusters(pb, pbio);
+       init_pb_bio(pbio);
+       calc_bio_clusters(pb, rq, pbio);
 
        key = pbio_last_required_for_backup_clu(pb, pbio);
        if (key != U64_MAX) {
+               pbio->rq = rq;
                pbio->key_clu = key;
                return true;
        }
@@ -167,34 +164,31 @@ static struct pb_bio *find_pending_pbio(struct 
push_backup *pb, u64 clu)
 }
 
 static void unlink_postponed_backup_pbio(struct push_backup *pb,
-                                        struct bio_list *bio_list,
+                                        struct list_head *pbio_list,
                                         struct pb_bio *pbio)
 {
-       struct bio *bio;
-
        lockdep_assert_held(&pb->lock);
 
        unlink_pending_pbio(pb, pbio);
        pb->nr_delayed -= 1;
 
-       bio = pbio_to_bio(pbio);
-       bio_list_add(bio_list, bio);
+       list_add_tail(&pbio->list, pbio_list);
 }
 
-static void resubmit_bios(struct push_backup *pb, struct bio_list *bl)
+static void resubmit_pbios(struct push_backup *pb, struct list_head *list)
 {
-       struct bio *bio;
+       struct pb_bio *pbio;
 
-       while ((bio = bio_list_pop(bl)) != NULL) {
-               remap_to_origin(pb, bio);
-               generic_make_request(bio);
+       while ((pbio = list_first_entry_or_null(list, struct pb_bio, list)) != 
NULL) {
+               list_del_init(&pbio->list);
+               dm_requeue_original_rq(pbio->rq);
        }
 }
 
 static void cleanup_backup(struct push_backup *pb)
 {
-       struct bio_list bio_list = BIO_EMPTY_LIST;
        struct hlist_node *tmp;
+       LIST_HEAD(pbio_list);
        struct pb_bio *pbio;
        int i;
 
@@ -203,7 +197,7 @@ static void cleanup_backup(struct push_backup *pb)
 
        for (i = 0; i < PB_HASH_TABLE_SIZE && pb->nr_delayed; i++) {
                hlist_for_each_entry_safe(pbio, tmp, &pb->pending_htable[i], 
hlist_node)
-                       unlink_postponed_backup_pbio(pb, &bio_list, pbio);
+                       unlink_postponed_backup_pbio(pb, &pbio_list, pbio);
        }
 
        WARN_ON_ONCE(pb->nr_delayed);
@@ -211,8 +205,8 @@ static void cleanup_backup(struct push_backup *pb)
 
        wake_up_interruptible(&pb->waitq); /* pb->alive = false */
 
-       if (!bio_list_empty(&bio_list))
-               resubmit_bios(pb, &bio_list);
+       if (!list_empty(&pbio_list))
+               resubmit_pbios(pb, &pbio_list);
 }
 
 static void do_pb_work(struct work_struct *ws)
@@ -239,15 +233,15 @@ static void pb_timer_func(struct timer_list *timer)
 }
 
 static bool postpone_if_required_for_backup(struct push_backup *pb,
-                                           struct bio *bio)
+                                           struct request *rq,
+                                           struct pb_bio *pbio)
 {
        bool queue_timer = false, postpone = false;
-       struct pb_bio *pbio = bio_to_pbio(bio);
        unsigned long flags;
 
        rcu_read_lock(); /* See push_backup_stop() */
        spin_lock_irqsave(&pb->lock, flags);
-       if (!pb->alive || !setup_if_required_for_backup(pb, pbio))
+       if (!pb->alive || !setup_if_required_for_backup(pb, rq, pbio))
                goto unlock;
 
        update_pending_map(pb, pbio);
@@ -272,29 +266,50 @@ static bool postpone_if_required_for_backup(struct 
push_backup *pb,
        return postpone;
 }
 
-static void init_pb_bio(struct bio *bio)
+static inline struct pb_bio *map_info_to_embedded_pbio(union map_info *info)
 {
-       struct pb_bio *pbio = bio_to_pbio(bio);
-
-       INIT_HLIST_NODE(&pbio->hlist_node);
-       INIT_LIST_HEAD(&pbio->list);
+       return (void *)info->ptr;
 }
 
-static int pb_map(struct dm_target *ti, struct bio *bio)
+static int pb_clone_and_map(struct dm_target *ti, struct request *rq,
+                                  union map_info *map_context,
+                                  struct request **__clone)
+
 {
+       struct pb_bio *pbio = map_info_to_embedded_pbio(map_context);
        struct push_backup *pb = ti->private;
+       struct block_device *bdev = pb->origin_dev->bdev;
+       struct request_queue *q;
+       struct request *clone;
 
-       init_pb_bio(bio);
-
-       if (bio_sectors(bio) && op_is_write(bio->bi_opf)) {
-               if (postpone_if_required_for_backup(pb, bio))
+       if (blk_rq_bytes(rq) && op_is_write(req_op(rq))) {
+               if (postpone_if_required_for_backup(pb, rq, pbio))
                        return DM_MAPIO_SUBMITTED;
        }
 
-       remap_to_origin(pb, bio);
+       q = bdev_get_queue(bdev);
+       clone = blk_get_request(q, rq->cmd_flags | REQ_NOMERGE,
+                               BLK_MQ_REQ_NOWAIT);
+       if (IS_ERR(clone)) {
+               /* EBUSY, ENODEV or EWOULDBLOCK: requeue */
+               if (blk_queue_dying(q))
+                       return DM_MAPIO_DELAY_REQUEUE;
+               return DM_MAPIO_REQUEUE;
+       }
+
+       clone->bio = clone->biotail = NULL;
+       clone->rq_disk = bdev->bd_disk;
+       clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+       *__clone = clone;
        return DM_MAPIO_REMAPPED;
 }
 
+static void pb_release_clone(struct request *clone,
+                            union map_info *map_context)
+{
+       blk_put_request(clone);
+}
+
 static bool msg_wants_down_read(const char *cmd)
 {
        if (!strcmp(cmd, "push_backup_read") ||
@@ -440,9 +455,9 @@ static int push_backup_read(struct push_backup *pb,
 static int push_backup_write(struct push_backup *pb,
                             unsigned int clu, unsigned int nr)
 {
-       struct bio_list bio_list = BIO_EMPTY_LIST;
        u64 i, key, nr_clus = pb->nr_clus;
        bool finished, has_more = false;
+       LIST_HEAD(pbio_list);
        struct pb_bio *pbio;
 
        if (!pb)
@@ -489,7 +504,7 @@ static int push_backup_write(struct push_backup *pb,
                         * All clusters of this bios were backuped or
                         * they are not needed for backup.
                         */
-                       unlink_postponed_backup_pbio(pb, &bio_list, pbio);
+                       unlink_postponed_backup_pbio(pb, &pbio_list, pbio);
                }
        }
 
@@ -503,8 +518,8 @@ static int push_backup_write(struct push_backup *pb,
        if (finished)
                wake_up_interruptible(&pb->waitq);
 
-       if (!bio_list_empty(&bio_list)) {
-               resubmit_bios(pb, &bio_list);
+       if (!list_empty(&pbio_list)) {
+               resubmit_pbios(pb, &pbio_list);
                if (has_more)
                        mod_timer(&pb->deadline_timer, pb->timeout_in_jiffies + 
1);
        }
@@ -740,7 +755,8 @@ static struct target_type pb_target = {
        .module = THIS_MODULE,
        .ctr = pb_ctr,
        .dtr = pb_dtr,
-       .map = pb_map,
+       .clone_and_map_rq = pb_clone_and_map,
+       .release_clone_rq = pb_release_clone,
        .message = pb_message,
        .iterate_devices = pb_iterate_devices,
        .postsuspend = pb_postsuspend,


_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to