block: pass iov_iter to the BLOCK_PC mapping functions
[linux-block.git] / block / bio.c
index 3e6e1986a5b2c0c217532b816dc911cd544e3e11..7d8c6555e3f3365fe88bbd9ce77ac49dfca0cfbe 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/mempool.h>
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
-#include <scsi/sg.h>           /* for struct sg_iovec */
 
 #include <trace/events/block.h>
 
@@ -748,6 +747,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                                }
                        }
 
+                       bio->bi_iter.bi_size += len;
                        goto done;
                }
 
@@ -764,28 +764,31 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                return 0;
 
        /*
-        * we might lose a segment or two here, but rather that than
-        * make this too complex.
+        * setup the new entry, we might clear it again later if we
+        * cannot add the page
         */
+       bvec = &bio->bi_io_vec[bio->bi_vcnt];
+       bvec->bv_page = page;
+       bvec->bv_len = len;
+       bvec->bv_offset = offset;
+       bio->bi_vcnt++;
+       bio->bi_phys_segments++;
+       bio->bi_iter.bi_size += len;
 
-       while (bio->bi_phys_segments >= queue_max_segments(q)) {
+       /*
+        * Perform a recount if the number of segments is greater
+        * than queue_max_segments(q).
+        */
+
+       while (bio->bi_phys_segments > queue_max_segments(q)) {
 
                if (retried_segments)
-                       return 0;
+                       goto failed;
 
                retried_segments = 1;
                blk_recount_segments(q, bio);
        }
 
-       /*
-        * setup the new entry, we might clear it again later if we
-        * cannot add the page
-        */
-       bvec = &bio->bi_io_vec[bio->bi_vcnt];
-       bvec->bv_page = page;
-       bvec->bv_len = len;
-       bvec->bv_offset = offset;
-
        /*
         * if queue has other restrictions (eg varying max sector size
         * depending on offset), it can specify a merge_bvec_fn in the
@@ -795,7 +798,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                struct bvec_merge_data bvm = {
                        .bi_bdev = bio->bi_bdev,
                        .bi_sector = bio->bi_iter.bi_sector,
-                       .bi_size = bio->bi_iter.bi_size,
+                       .bi_size = bio->bi_iter.bi_size - len,
                        .bi_rw = bio->bi_rw,
                };
 
@@ -803,23 +806,25 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                 * merge_bvec_fn() returns number of bytes it can accept
                 * at this offset
                 */
-               if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len) {
-                       bvec->bv_page = NULL;
-                       bvec->bv_len = 0;
-                       bvec->bv_offset = 0;
-                       return 0;
-               }
+               if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len)
+                       goto failed;
        }
 
        /* If we may be able to merge these biovecs, force a recount */
-       if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec)))
+       if (bio->bi_vcnt > 1 && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec)))
                bio->bi_flags &= ~(1 << BIO_SEG_VALID);
 
-       bio->bi_vcnt++;
-       bio->bi_phys_segments++;
  done:
-       bio->bi_iter.bi_size += len;
        return len;
+
+ failed:
+       bvec->bv_page = NULL;
+       bvec->bv_len = 0;
+       bvec->bv_offset = 0;
+       bio->bi_vcnt--;
+       bio->bi_iter.bi_size -= len;
+       blk_recount_segments(q, bio);
+       return 0;
 }
 
 /**
@@ -1016,21 +1021,11 @@ void bio_copy_data(struct bio *dst, struct bio *src)
 EXPORT_SYMBOL(bio_copy_data);
 
 struct bio_map_data {
-       int nr_sgvecs;
        int is_our_pages;
-       struct sg_iovec sgvecs[];
+       struct iov_iter iter;
+       struct iovec iov[];
 };
 
-static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio,
-                            const struct sg_iovec *iov, int iov_count,
-                            int is_our_pages)
-{
-       memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count);
-       bmd->nr_sgvecs = iov_count;
-       bmd->is_our_pages = is_our_pages;
-       bio->bi_private = bmd;
-}
-
 static struct bio_map_data *bio_alloc_map_data(unsigned int iov_count,
                                               gfp_t gfp_mask)
 {
@@ -1038,36 +1033,33 @@ static struct bio_map_data *bio_alloc_map_data(unsigned int iov_count,
                return NULL;
 
        return kmalloc(sizeof(struct bio_map_data) +
-                      sizeof(struct sg_iovec) * iov_count, gfp_mask);
+                      sizeof(struct iovec) * iov_count, gfp_mask);
 }
 
-static int __bio_copy_iov(struct bio *bio, const struct sg_iovec *iov, int iov_count,
-                         int to_user, int from_user, int do_free_page)
+static int __bio_copy_iov(struct bio *bio, const struct iov_iter *iter,
+                         int to_user, int from_user)
 {
        int ret = 0, i;
        struct bio_vec *bvec;
-       int iov_idx = 0;
-       unsigned int iov_off = 0;
+       struct iov_iter iov_iter = *iter;
 
        bio_for_each_segment_all(bvec, bio, i) {
                char *bv_addr = page_address(bvec->bv_page);
                unsigned int bv_len = bvec->bv_len;
 
-               while (bv_len && iov_idx < iov_count) {
-                       unsigned int bytes;
-                       char __user *iov_addr;
-
-                       bytes = min_t(unsigned int,
-                                     iov[iov_idx].iov_len - iov_off, bv_len);
-                       iov_addr = iov[iov_idx].iov_base + iov_off;
+               while (bv_len && iov_iter.count) {
+                       struct iovec iov = iov_iter_iovec(&iov_iter);
+                       unsigned int bytes = min_t(unsigned int, bv_len,
+                                                  iov.iov_len);
 
                        if (!ret) {
                                if (to_user)
-                                       ret = copy_to_user(iov_addr, bv_addr,
-                                                          bytes);
+                                       ret = copy_to_user(iov.iov_base,
+                                                          bv_addr, bytes);
 
                                if (from_user)
-                                       ret = copy_from_user(bv_addr, iov_addr,
+                                       ret = copy_from_user(bv_addr,
+                                                            iov.iov_base,
                                                             bytes);
 
                                if (ret)
@@ -1076,34 +1068,33 @@ static int __bio_copy_iov(struct bio *bio, const struct sg_iovec *iov, int iov_c
 
                        bv_len -= bytes;
                        bv_addr += bytes;
-                       iov_addr += bytes;
-                       iov_off += bytes;
-
-                       if (iov[iov_idx].iov_len == iov_off) {
-                               iov_idx++;
-                               iov_off = 0;
-                       }
+                       iov_iter_advance(&iov_iter, bytes);
                }
-
-               if (do_free_page)
-                       __free_page(bvec->bv_page);
        }
 
        return ret;
 }
 
+static void bio_free_pages(struct bio *bio)
+{
+       struct bio_vec *bvec;
+       int i;
+
+       bio_for_each_segment_all(bvec, bio, i)
+               __free_page(bvec->bv_page);
+}
+
 /**
  *     bio_uncopy_user -       finish previously mapped bio
  *     @bio: bio being terminated
  *
- *     Free pages allocated from bio_copy_user() and write back data
+ *     Free pages allocated from bio_copy_user_iov() and write back data
  *     to user space in case of a read.
  */
 int bio_uncopy_user(struct bio *bio)
 {
        struct bio_map_data *bmd = bio->bi_private;
-       struct bio_vec *bvec;
-       int ret = 0, i;
+       int ret = 0;
 
        if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
                /*
@@ -1111,12 +1102,10 @@ int bio_uncopy_user(struct bio *bio)
                 * don't copy into a random user address space, just free.
                 */
                if (current->mm)
-                       ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs,
-                                            bio_data_dir(bio) == READ,
-                                            0, bmd->is_our_pages);
-               else if (bmd->is_our_pages)
-                       bio_for_each_segment_all(bvec, bio, i)
-                               __free_page(bvec->bv_page);
+                       ret = __bio_copy_iov(bio, &bmd->iter,
+                                            bio_data_dir(bio) == READ, 0);
+               if (bmd->is_our_pages)
+                       bio_free_pages(bio);
        }
        kfree(bmd);
        bio_put(bio);
@@ -1126,12 +1115,10 @@ EXPORT_SYMBOL(bio_uncopy_user);
 
 /**
  *     bio_copy_user_iov       -       copy user data to bio
- *     @q: destination block queue
- *     @map_data: pointer to the rq_map_data holding pages (if necessary)
- *     @iov:   the iovec.
- *     @iov_count: number of elements in the iovec
- *     @write_to_vm: bool indicating writing to pages or not
- *     @gfp_mask: memory allocation flags
+ *     @q:             destination block queue
+ *     @map_data:      pointer to the rq_map_data holding pages (if necessary)
+ *     @iter:          iovec iterator
+ *     @gfp_mask:      memory allocation flags
  *
  *     Prepares and returns a bio for indirect user io, bouncing data
  *     to/from kernel pages as necessary. Must be paired with
@@ -1139,25 +1126,25 @@ EXPORT_SYMBOL(bio_uncopy_user);
  */
 struct bio *bio_copy_user_iov(struct request_queue *q,
                              struct rq_map_data *map_data,
-                             const struct sg_iovec *iov, int iov_count,
-                             int write_to_vm, gfp_t gfp_mask)
+                             const struct iov_iter *iter,
+                             gfp_t gfp_mask)
 {
        struct bio_map_data *bmd;
-       struct bio_vec *bvec;
        struct page *page;
        struct bio *bio;
        int i, ret;
        int nr_pages = 0;
-       unsigned int len = 0;
+       unsigned int len = iter->count;
        unsigned int offset = map_data ? map_data->offset & ~PAGE_MASK : 0;
 
-       for (i = 0; i < iov_count; i++) {
+       for (i = 0; i < iter->nr_segs; i++) {
                unsigned long uaddr;
                unsigned long end;
                unsigned long start;
 
-               uaddr = (unsigned long)iov[i].iov_base;
-               end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               uaddr = (unsigned long) iter->iov[i].iov_base;
+               end = (uaddr + iter->iov[i].iov_len + PAGE_SIZE - 1)
+                       >> PAGE_SHIFT;
                start = uaddr >> PAGE_SHIFT;
 
                /*
@@ -1167,22 +1154,31 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
                        return ERR_PTR(-EINVAL);
 
                nr_pages += end - start;
-               len += iov[i].iov_len;
        }
 
        if (offset)
                nr_pages++;
 
-       bmd = bio_alloc_map_data(iov_count, gfp_mask);
+       bmd = bio_alloc_map_data(iter->nr_segs, gfp_mask);
        if (!bmd)
                return ERR_PTR(-ENOMEM);
 
+       /*
+        * We need to do a deep copy of the iov_iter including the iovecs.
+        * The caller provided iov might point to an on-stack or otherwise
+        * shortlived one.
+        */
+       bmd->is_our_pages = map_data ? 0 : 1;
+       memcpy(bmd->iov, iter->iov, sizeof(struct iovec) * iter->nr_segs);
+       iov_iter_init(&bmd->iter, iter->type, bmd->iov,
+                       iter->nr_segs, iter->count);
+
        ret = -ENOMEM;
        bio = bio_kmalloc(gfp_mask, nr_pages);
        if (!bio)
                goto out_bmd;
 
-       if (!write_to_vm)
+       if (iter->type & WRITE)
                bio->bi_rw |= REQ_WRITE;
 
        ret = 0;
@@ -1230,67 +1226,41 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
        /*
         * success
         */
-       if ((!write_to_vm && (!map_data || !map_data->null_mapped)) ||
+       if (((iter->type & WRITE) && (!map_data || !map_data->null_mapped)) ||
            (map_data && map_data->from_user)) {
-               ret = __bio_copy_iov(bio, iov, iov_count, 0, 1, 0);
+               ret = __bio_copy_iov(bio, iter, 0, 1);
                if (ret)
                        goto cleanup;
        }
 
-       bio_set_map_data(bmd, bio, iov, iov_count, map_data ? 0 : 1);
+       bio->bi_private = bmd;
        return bio;
 cleanup:
        if (!map_data)
-               bio_for_each_segment_all(bvec, bio, i)
-                       __free_page(bvec->bv_page);
-
+               bio_free_pages(bio);
        bio_put(bio);
 out_bmd:
        kfree(bmd);
        return ERR_PTR(ret);
 }
 
-/**
- *     bio_copy_user   -       copy user data to bio
- *     @q: destination block queue
- *     @map_data: pointer to the rq_map_data holding pages (if necessary)
- *     @uaddr: start of user address
- *     @len: length in bytes
- *     @write_to_vm: bool indicating writing to pages or not
- *     @gfp_mask: memory allocation flags
- *
- *     Prepares and returns a bio for indirect user io, bouncing data
- *     to/from kernel pages as necessary. Must be paired with
- *     call bio_uncopy_user() on io completion.
- */
-struct bio *bio_copy_user(struct request_queue *q, struct rq_map_data *map_data,
-                         unsigned long uaddr, unsigned int len,
-                         int write_to_vm, gfp_t gfp_mask)
-{
-       struct sg_iovec iov;
-
-       iov.iov_base = (void __user *)uaddr;
-       iov.iov_len = len;
-
-       return bio_copy_user_iov(q, map_data, &iov, 1, write_to_vm, gfp_mask);
-}
-EXPORT_SYMBOL(bio_copy_user);
-
 static struct bio *__bio_map_user_iov(struct request_queue *q,
                                      struct block_device *bdev,
-                                     const struct sg_iovec *iov, int iov_count,
-                                     int write_to_vm, gfp_t gfp_mask)
+                                     const struct iov_iter *iter,
+                                     gfp_t gfp_mask)
 {
-       int i, j;
+       int j;
        int nr_pages = 0;
        struct page **pages;
        struct bio *bio;
        int cur_page = 0;
        int ret, offset;
+       struct iov_iter i;
+       struct iovec iov;
 
-       for (i = 0; i < iov_count; i++) {
-               unsigned long uaddr = (unsigned long)iov[i].iov_base;
-               unsigned long len = iov[i].iov_len;
+       iov_for_each(iov, i, *iter) {
+               unsigned long uaddr = (unsigned long) iov.iov_base;
+               unsigned long len = iov.iov_len;
                unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
                unsigned long start = uaddr >> PAGE_SHIFT;
 
@@ -1320,16 +1290,17 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
        if (!pages)
                goto out;
 
-       for (i = 0; i < iov_count; i++) {
-               unsigned long uaddr = (unsigned long)iov[i].iov_base;
-               unsigned long len = iov[i].iov_len;
+       iov_for_each(iov, i, *iter) {
+               unsigned long uaddr = (unsigned long) iov.iov_base;
+               unsigned long len = iov.iov_len;
                unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
                unsigned long start = uaddr >> PAGE_SHIFT;
                const int local_nr_pages = end - start;
                const int page_limit = cur_page + local_nr_pages;
 
                ret = get_user_pages_fast(uaddr, local_nr_pages,
-                               write_to_vm, &pages[cur_page]);
+                               (iter->type & WRITE) != WRITE,
+                               &pages[cur_page]);
                if (ret < local_nr_pages) {
                        ret = -EFAULT;
                        goto out_unmap;
@@ -1369,7 +1340,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
        /*
         * set data direction, and check if mapped pages need bouncing
         */
-       if (!write_to_vm)
+       if (iter->type & WRITE)
                bio->bi_rw |= REQ_WRITE;
 
        bio->bi_bdev = bdev;
@@ -1377,10 +1348,10 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
        return bio;
 
  out_unmap:
-       for (i = 0; i < nr_pages; i++) {
-               if(!pages[i])
+       for (j = 0; j < nr_pages; j++) {
+               if (!pages[j])
                        break;
-               page_cache_release(pages[i]);
+               page_cache_release(pages[j]);
        }
  out:
        kfree(pages);
@@ -1389,50 +1360,22 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
 }
 
 /**
- *     bio_map_user    -       map user address into bio
- *     @q: the struct request_queue for the bio
- *     @bdev: destination block device
- *     @uaddr: start of user address
- *     @len: length in bytes
- *     @write_to_vm: bool indicating writing to pages or not
- *     @gfp_mask: memory allocation flags
- *
- *     Map the user space address into a bio suitable for io to a block
- *     device. Returns an error pointer in case of error.
- */
-struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev,
-                        unsigned long uaddr, unsigned int len, int write_to_vm,
-                        gfp_t gfp_mask)
-{
-       struct sg_iovec iov;
-
-       iov.iov_base = (void __user *)uaddr;
-       iov.iov_len = len;
-
-       return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm, gfp_mask);
-}
-EXPORT_SYMBOL(bio_map_user);
-
-/**
- *     bio_map_user_iov - map user sg_iovec table into bio
- *     @q: the struct request_queue for the bio
- *     @bdev: destination block device
- *     @iov:   the iovec.
- *     @iov_count: number of elements in the iovec
- *     @write_to_vm: bool indicating writing to pages or not
- *     @gfp_mask: memory allocation flags
+ *     bio_map_user_iov - map user iovec into bio
+ *     @q:             the struct request_queue for the bio
+ *     @bdev:          destination block device
+ *     @iter:          iovec iterator
+ *     @gfp_mask:      memory allocation flags
  *
  *     Map the user space address into a bio suitable for io to a block
  *     device. Returns an error pointer in case of error.
  */
 struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev,
-                            const struct sg_iovec *iov, int iov_count,
-                            int write_to_vm, gfp_t gfp_mask)
+                            const struct iov_iter *iter,
+                            gfp_t gfp_mask)
 {
        struct bio *bio;
 
-       bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm,
-                                gfp_mask);
+       bio = __bio_map_user_iov(q, bdev, iter, gfp_mask);
        if (IS_ERR(bio))
                return bio;
 
@@ -1555,24 +1498,22 @@ EXPORT_SYMBOL(bio_map_kern);
 
 static void bio_copy_kern_endio(struct bio *bio, int err)
 {
+       bio_free_pages(bio);
+       bio_put(bio);
+}
+
+static void bio_copy_kern_endio_read(struct bio *bio, int err)
+{
+       char *p = bio->bi_private;
        struct bio_vec *bvec;
-       const int read = bio_data_dir(bio) == READ;
-       struct bio_map_data *bmd = bio->bi_private;
        int i;
-       char *p = bmd->sgvecs[0].iov_base;
 
        bio_for_each_segment_all(bvec, bio, i) {
-               char *addr = page_address(bvec->bv_page);
-
-               if (read)
-                       memcpy(p, addr, bvec->bv_len);
-
-               __free_page(bvec->bv_page);
+               memcpy(p, page_address(bvec->bv_page), bvec->bv_len);
                p += bvec->bv_len;
        }
 
-       kfree(bmd);
-       bio_put(bio);
+       bio_copy_kern_endio(bio, err);
 }
 
 /**
@@ -1589,28 +1530,59 @@ static void bio_copy_kern_endio(struct bio *bio, int err)
 struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
                          gfp_t gfp_mask, int reading)
 {
+       unsigned long kaddr = (unsigned long)data;
+       unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       unsigned long start = kaddr >> PAGE_SHIFT;
        struct bio *bio;
-       struct bio_vec *bvec;
-       int i;
+       void *p = data;
+       int nr_pages = 0;
 
-       bio = bio_copy_user(q, NULL, (unsigned long)data, len, 1, gfp_mask);
-       if (IS_ERR(bio))
-               return bio;
+       /*
+        * Overflow, abort
+        */
+       if (end < start)
+               return ERR_PTR(-EINVAL);
 
-       if (!reading) {
-               void *p = data;
+       nr_pages = end - start;
+       bio = bio_kmalloc(gfp_mask, nr_pages);
+       if (!bio)
+               return ERR_PTR(-ENOMEM);
 
-               bio_for_each_segment_all(bvec, bio, i) {
-                       char *addr = page_address(bvec->bv_page);
+       while (len) {
+               struct page *page;
+               unsigned int bytes = PAGE_SIZE;
 
-                       memcpy(addr, p, bvec->bv_len);
-                       p += bvec->bv_len;
-               }
+               if (bytes > len)
+                       bytes = len;
+
+               page = alloc_page(q->bounce_gfp | gfp_mask);
+               if (!page)
+                       goto cleanup;
+
+               if (!reading)
+                       memcpy(page_address(page), p, bytes);
+
+               if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
+                       break;
+
+               len -= bytes;
+               p += bytes;
        }
 
-       bio->bi_end_io = bio_copy_kern_endio;
+       if (reading) {
+               bio->bi_end_io = bio_copy_kern_endio_read;
+               bio->bi_private = data;
+       } else {
+               bio->bi_end_io = bio_copy_kern_endio;
+               bio->bi_rw |= REQ_WRITE;
+       }
 
        return bio;
+
+cleanup:
+       bio_free_pages(bio);
+       bio_put(bio);
+       return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(bio_copy_kern);
 
@@ -1739,6 +1711,34 @@ void bio_check_pages_dirty(struct bio *bio)
        }
 }
 
+void generic_start_io_acct(int rw, unsigned long sectors,
+                          struct hd_struct *part)
+{
+       int cpu = part_stat_lock();
+
+       part_round_stats(cpu, part);
+       part_stat_inc(cpu, part, ios[rw]);
+       part_stat_add(cpu, part, sectors[rw], sectors);
+       part_inc_in_flight(part, rw);
+
+       part_stat_unlock();
+}
+EXPORT_SYMBOL(generic_start_io_acct);
+
+void generic_end_io_acct(int rw, struct hd_struct *part,
+                        unsigned long start_time)
+{
+       unsigned long duration = jiffies - start_time;
+       int cpu = part_stat_lock();
+
+       part_stat_add(cpu, part, ticks[rw], duration);
+       part_round_stats(cpu, part);
+       part_dec_in_flight(part, rw);
+
+       part_stat_unlock();
+}
+EXPORT_SYMBOL(generic_end_io_acct);
+
 #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
 void bio_flush_dcache_pages(struct bio *bi)
 {