We use merge_bvec_fn to make sure that copies do not split internal
boundaries of device mapper devices.

There is no possibility to split a copy bio (splitting would complicate
the design significantly), so we must use merge_bvec_fn to make sure that
the bios have appropriate size for the device mapper stack.

Signed-off-by: Mikulas Patocka <mpato...@redhat.com>

---
 block/blk-lib.c |   37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

Index: linux-3.16-rc5/block/blk-lib.c
===================================================================
--- linux-3.16-rc5.orig/block/blk-lib.c 2014-07-15 15:27:51.000000000 +0200
+++ linux-3.16-rc5/block/blk-lib.c      2014-07-15 15:27:59.000000000 +0200
@@ -369,6 +369,31 @@ static void bio_copy_end_io(struct bio *
        }
 }
 
+static unsigned blkdev_copy_merge(struct block_device *bdev,
+                                 struct request_queue *q, unsigned long bi_rw,
+                                 sector_t sector, unsigned n)
+{
+       if (!q->merge_bvec_fn) {
+               return n;
+       } else {
+               unsigned m;
+               struct bvec_merge_data bvm = {
+                       .bi_bdev = bdev,
+                       .bi_sector = sector,
+                       .bi_size = 0,
+                       .bi_rw = bi_rw,
+               };
+               struct bio_vec vec = {
+                       .bv_page = NULL,
+                       .bv_len = likely(n <= UINT_MAX >> 9) ? n << 9 : 
UINT_MAX & ~511U,
+                       .bv_offset = 0,
+               };
+               m = q->merge_bvec_fn(q, &bvm, &vec);
+               m >>= 9;
+               return min(m, n);
+       }
+}
+
 /**
  * blkdev_issue_copy - queue a copy same operation
  * @src_bdev:  source blockdev
@@ -424,6 +449,18 @@ int blkdev_issue_copy(struct block_devic
                struct bio_copy *bc;
                unsigned chunk = (unsigned)min(nr_sects, 
(sector_t)max_copy_sectors);
 
+               chunk = blkdev_copy_merge(src_bdev, sq, READ | REQ_COPY, 
src_sector, chunk);
+               if (!chunk) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
+               chunk = blkdev_copy_merge(dst_bdev, dq, WRITE | REQ_COPY, 
dst_sector, chunk);
+               if (!chunk) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
                bc = kmalloc(sizeof(struct bio_copy), gfp_mask);
                if (!bc) {
                        ret = -ENOMEM;

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to