checkpatch: pull out known acceptable typedefs
[safe/jmp/linux-2.6] / fs / bio.c
index 7a6598a..77a55bc 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -30,7 +30,7 @@
 
 static struct kmem_cache *bio_slab __read_mostly;
 
-mempool_t *bio_split_pool __read_mostly;
+static mempool_t *bio_split_pool __read_mostly;
 
 /*
  * if you change this list, also change bvec_alloc or things will
@@ -50,33 +50,56 @@ static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
  */
 struct bio_set *fs_bio_set;
 
+unsigned int bvec_nr_vecs(unsigned short idx)
+{
+       return bvec_slabs[idx].nr_vecs;
+}
+
 struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
 {
        struct bio_vec *bvl;
 
        /*
-        * see comment near bvec_array define!
+        * If 'bs' is given, lookup the pool and do the mempool alloc.
+        * If not, this is a bio_kmalloc() allocation and just do a
+        * kzalloc() for the exact number of vecs right away.
         */
-       switch (nr) {
-               case   1        : *idx = 0; break;
-               case   2 ...   4: *idx = 1; break;
-               case   5 ...  16: *idx = 2; break;
-               case  17 ...  64: *idx = 3; break;
-               case  65 ... 128: *idx = 4; break;
-               case 129 ... BIO_MAX_PAGES: *idx = 5; break;
+       if (bs) {
+               /*
+                * see comment near bvec_array define!
+                */
+               switch (nr) {
+               case 1:
+                       *idx = 0;
+                       break;
+               case 2 ... 4:
+                       *idx = 1;
+                       break;
+               case 5 ... 16:
+                       *idx = 2;
+                       break;
+               case 17 ... 64:
+                       *idx = 3;
+                       break;
+               case 65 ... 128:
+                       *idx = 4;
+                       break;
+               case 129 ... BIO_MAX_PAGES:
+                       *idx = 5;
+                       break;
                default:
                        return NULL;
-       }
-       /*
-        * idx now points to the pool we want to allocate from
-        */
-
-       bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
-       if (bvl) {
-               struct biovec_slab *bp = bvec_slabs + *idx;
+               }
 
-               memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
-       }
+               /*
+                * idx now points to the pool we want to allocate from
+                */
+               bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
+               if (bvl)
+                       memset(bvl, 0,
+                               bvec_nr_vecs(*idx) * sizeof(struct bio_vec));
+       } else
+               bvl = kzalloc(nr * sizeof(struct bio_vec), gfp_mask);
 
        return bvl;
 }
@@ -91,6 +114,9 @@ void bio_free(struct bio *bio, struct bio_set *bio_set)
                mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
        }
 
+       if (bio_integrity(bio))
+               bio_integrity_free(bio, bio_set);
+
        mempool_free(bio, bio_set->bio_pool);
 }
 
@@ -102,10 +128,17 @@ static void bio_fs_destructor(struct bio *bio)
        bio_free(bio, fs_bio_set);
 }
 
+static void bio_kmalloc_destructor(struct bio *bio)
+{
+       kfree(bio->bi_io_vec);
+       kfree(bio);
+}
+
 void bio_init(struct bio *bio)
 {
        memset(bio, 0, sizeof(*bio));
        bio->bi_flags = 1 << BIO_UPTODATE;
+       bio->bi_comp_cpu = -1;
        atomic_set(&bio->bi_cnt, 1);
 }
 
@@ -113,19 +146,25 @@ void bio_init(struct bio *bio)
  * bio_alloc_bioset - allocate a bio for I/O
  * @gfp_mask:   the GFP_ mask given to the slab allocator
  * @nr_iovecs: number of iovecs to pre-allocate
- * @bs:                the bio_set to allocate from
+ * @bs:                the bio_set to allocate from. If %NULL, just use kmalloc
  *
  * Description:
- *   bio_alloc_bioset will first try it's on mempool to satisfy the allocation.
+ *   bio_alloc_bioset will first try its own mempool to satisfy the allocation.
  *   If %__GFP_WAIT is set then we will block on the internal pool waiting
- *   for a &struct bio to become free.
+ *   for a &struct bio to become free. If a %NULL @bs is passed in, we will
+ *   fall back to just using @kmalloc to allocate the required memory.
  *
  *   allocate bio and iovecs from the memory pools specified by the
- *   bio_set structure.
+ *   bio_set structure, or @kmalloc if none given.
  **/
 struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
-       struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask);
+       struct bio *bio;
+
+       if (bs)
+               bio = mempool_alloc(bs->bio_pool, gfp_mask);
+       else
+               bio = kmalloc(sizeof(*bio), gfp_mask);
 
        if (likely(bio)) {
                struct bio_vec *bvl = NULL;
@@ -136,12 +175,15 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 
                        bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
                        if (unlikely(!bvl)) {
-                               mempool_free(bio, bs->bio_pool);
+                               if (bs)
+                                       mempool_free(bio, bs->bio_pool);
+                               else
+                                       kfree(bio);
                                bio = NULL;
                                goto out;
                        }
                        bio->bi_flags |= idx << BIO_POOL_OFFSET;
-                       bio->bi_max_vecs = bvec_slabs[idx].nr_vecs;
+                       bio->bi_max_vecs = bvec_nr_vecs(idx);
                }
                bio->bi_io_vec = bvl;
        }
@@ -159,6 +201,23 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
        return bio;
 }
 
+/*
+ * Like bio_alloc(), but doesn't use a mempool backing. This means that
+ * it CAN fail, but while bio_alloc() can only be used for allocations
+ * that have a short (finite) life span, bio_kmalloc() should be used
+ * for more permanent bio allocations (like allocating some bio's for
+ * initalization or setup purposes).
+ */
+struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
+{
+       struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);
+
+       if (bio)
+               bio->bi_destructor = bio_kmalloc_destructor;
+
+       return bio;
+}
+
 void zero_fill_bio(struct bio *bio)
 {
        unsigned long flags;
@@ -203,14 +262,6 @@ inline int bio_phys_segments(struct request_queue *q, struct bio *bio)
        return bio->bi_phys_segments;
 }
 
-inline int bio_hw_segments(struct request_queue *q, struct bio *bio)
-{
-       if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
-               blk_recount_segments(q, bio);
-
-       return bio->bi_hw_segments;
-}
-
 /**
  *     __bio_clone     -       clone a bio
  *     @bio: destination bio
@@ -249,9 +300,19 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
 {
        struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
 
-       if (b) {
-               b->bi_destructor = bio_fs_destructor;
-               __bio_clone(b, bio);
+       if (!b)
+               return NULL;
+
+       b->bi_destructor = bio_fs_destructor;
+       __bio_clone(b, bio);
+
+       if (bio_integrity(bio)) {
+               int ret;
+
+               ret = bio_integrity_clone(b, bio, fs_bio_set);
+
+               if (ret < 0)
+                       return NULL;
        }
 
        return b;
@@ -307,10 +368,19 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                if (page == prev->bv_page &&
                    offset == prev->bv_offset + prev->bv_len) {
                        prev->bv_len += len;
-                       if (q->merge_bvec_fn &&
-                           q->merge_bvec_fn(q, bio, prev) < len) {
-                               prev->bv_len -= len;
-                               return 0;
+
+                       if (q->merge_bvec_fn) {
+                               struct bvec_merge_data bvm = {
+                                       .bi_bdev = bio->bi_bdev,
+                                       .bi_sector = bio->bi_sector,
+                                       .bi_size = bio->bi_size,
+                                       .bi_rw = bio->bi_rw,
+                               };
+
+                               if (q->merge_bvec_fn(q, &bvm, prev) < len) {
+                                       prev->bv_len -= len;
+                                       return 0;
+                               }
                        }
 
                        goto done;
@@ -326,8 +396,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
         */
 
        while (bio->bi_phys_segments >= q->max_phys_segments
-              || bio->bi_hw_segments >= q->max_hw_segments
-              || BIOVEC_VIRT_OVERSIZE(bio->bi_size)) {
+              || bio->bi_phys_segments >= q->max_hw_segments) {
 
                if (retried_segments)
                        return 0;
@@ -351,11 +420,18 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
         * queue to get further control
         */
        if (q->merge_bvec_fn) {
+               struct bvec_merge_data bvm = {
+                       .bi_bdev = bio->bi_bdev,
+                       .bi_sector = bio->bi_sector,
+                       .bi_size = bio->bi_size,
+                       .bi_rw = bio->bi_rw,
+               };
+
                /*
                 * merge_bvec_fn() returns number of bytes it can accept
                 * at this offset
                 */
-               if (q->merge_bvec_fn(q, bio, bvec) < len) {
+               if (q->merge_bvec_fn(q, &bvm, bvec) < len) {
                        bvec->bv_page = NULL;
                        bvec->bv_len = 0;
                        bvec->bv_offset = 0;
@@ -364,13 +440,11 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
        }
 
        /* If we may be able to merge these biovecs, force a recount */
-       if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec) ||
-           BIOVEC_VIRT_MERGEABLE(bvec-1, bvec)))
+       if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec)))
                bio->bi_flags &= ~(1 << BIO_SEG_VALID);
 
        bio->bi_vcnt++;
        bio->bi_phys_segments++;
-       bio->bi_hw_segments++;
  done:
        bio->bi_size += len;
        return len;
@@ -418,16 +492,19 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
 
 struct bio_map_data {
        struct bio_vec *iovecs;
-       int nr_sgvecs;
        struct sg_iovec *sgvecs;
+       int nr_sgvecs;
+       int is_our_pages;
 };
 
 static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio,
-                            struct sg_iovec *iov, int iov_count)
+                            struct sg_iovec *iov, int iov_count,
+                            int is_our_pages)
 {
        memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
        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;
 }
 
@@ -438,20 +515,21 @@ static void bio_free_map_data(struct bio_map_data *bmd)
        kfree(bmd);
 }
 
-static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count)
+static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count,
+                                              gfp_t gfp_mask)
 {
-       struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL);
+       struct bio_map_data *bmd = kmalloc(sizeof(*bmd), gfp_mask);
 
        if (!bmd)
                return NULL;
 
-       bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL);
+       bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, gfp_mask);
        if (!bmd->iovecs) {
                kfree(bmd);
                return NULL;
        }
 
-       bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, GFP_KERNEL);
+       bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, gfp_mask);
        if (bmd->sgvecs)
                return bmd;
 
@@ -460,8 +538,9 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count)
        return NULL;
 }
 
-static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
-                         int uncopy)
+static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
+                         struct sg_iovec *iov, int iov_count, int uncopy,
+                         int do_free_page)
 {
        int ret = 0, i;
        struct bio_vec *bvec;
@@ -471,7 +550,7 @@ static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
 
        __bio_for_each_segment(bvec, bio, i, 0) {
                char *bv_addr = page_address(bvec->bv_page);
-               unsigned int bv_len = bvec->bv_len;
+               unsigned int bv_len = iovecs[i].bv_len;
 
                while (bv_len && iov_idx < iov_count) {
                        unsigned int bytes;
@@ -504,7 +583,7 @@ static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
                        }
                }
 
-               if (uncopy)
+               if (do_free_page)
                        __free_page(bvec->bv_page);
        }
 
@@ -521,10 +600,11 @@ static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
 int bio_uncopy_user(struct bio *bio)
 {
        struct bio_map_data *bmd = bio->bi_private;
-       int ret;
-
-       ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, 1);
+       int ret = 0;
 
+       if (!bio_flagged(bio, BIO_NULL_MAPPED))
+               ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
+                                    bmd->nr_sgvecs, 1, bmd->is_our_pages);
        bio_free_map_data(bmd);
        bio_put(bio);
        return ret;
@@ -533,16 +613,20 @@ int bio_uncopy_user(struct bio *bio)
 /**
  *     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
  *
  *     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_iov(struct request_queue *q, struct sg_iovec *iov,
-                             int iov_count, int write_to_vm)
+struct bio *bio_copy_user_iov(struct request_queue *q,
+                             struct rq_map_data *map_data,
+                             struct sg_iovec *iov, int iov_count,
+                             int write_to_vm, gfp_t gfp_mask)
 {
        struct bio_map_data *bmd;
        struct bio_vec *bvec;
@@ -565,25 +649,38 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov,
                len += iov[i].iov_len;
        }
 
-       bmd = bio_alloc_map_data(nr_pages, iov_count);
+       bmd = bio_alloc_map_data(nr_pages, iov_count, gfp_mask);
        if (!bmd)
                return ERR_PTR(-ENOMEM);
 
        ret = -ENOMEM;
-       bio = bio_alloc(GFP_KERNEL, nr_pages);
+       bio = bio_alloc(gfp_mask, nr_pages);
        if (!bio)
                goto out_bmd;
 
        bio->bi_rw |= (!write_to_vm << BIO_RW);
 
        ret = 0;
+       i = 0;
        while (len) {
-               unsigned int bytes = PAGE_SIZE;
+               unsigned int bytes;
+
+               if (map_data)
+                       bytes = 1U << (PAGE_SHIFT + map_data->page_order);
+               else
+                       bytes = PAGE_SIZE;
 
                if (bytes > len)
                        bytes = len;
 
-               page = alloc_page(q->bounce_gfp | GFP_KERNEL);
+               if (map_data) {
+                       if (i == map_data->nr_entries) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       page = map_data->pages[i++];
+               } else
+                       page = alloc_page(q->bounce_gfp | gfp_mask);
                if (!page) {
                        ret = -ENOMEM;
                        break;
@@ -602,16 +699,17 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov,
         * success
         */
        if (!write_to_vm) {
-               ret = __bio_copy_iov(bio, iov, iov_count, 0);
+               ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0);
                if (ret)
                        goto cleanup;
        }
 
-       bio_set_map_data(bmd, bio, iov, iov_count);
+       bio_set_map_data(bmd, bio, iov, iov_count, map_data ? 0 : 1);
        return bio;
 cleanup:
-       bio_for_each_segment(bvec, bio, i)
-               __free_page(bvec->bv_page);
+       if (!map_data)
+               bio_for_each_segment(bvec, bio, i)
+                       __free_page(bvec->bv_page);
 
        bio_put(bio);
 out_bmd:
@@ -622,29 +720,32 @@ out_bmd:
 /**
  *     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, unsigned long uaddr,
-                         unsigned int len, int write_to_vm)
+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, &iov, 1, write_to_vm);
+       return bio_copy_user_iov(q, map_data, &iov, 1, write_to_vm, gfp_mask);
 }
 
 static struct bio *__bio_map_user_iov(struct request_queue *q,
                                      struct block_device *bdev,
                                      struct sg_iovec *iov, int iov_count,
-                                     int write_to_vm)
+                                     int write_to_vm, gfp_t gfp_mask)
 {
        int i, j;
        int nr_pages = 0;
@@ -670,12 +771,12 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
        if (!nr_pages)
                return ERR_PTR(-EINVAL);
 
-       bio = bio_alloc(GFP_KERNEL, nr_pages);
+       bio = bio_alloc(gfp_mask, nr_pages);
        if (!bio)
                return ERR_PTR(-ENOMEM);
 
        ret = -ENOMEM;
-       pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
+       pages = kcalloc(nr_pages, sizeof(struct page *), gfp_mask);
        if (!pages)
                goto out;
 
@@ -687,12 +788,8 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
                const int local_nr_pages = end - start;
                const int page_limit = cur_page + local_nr_pages;
                
-               down_read(&current->mm->mmap_sem);
-               ret = get_user_pages(current, current->mm, uaddr,
-                                    local_nr_pages,
-                                    write_to_vm, 0, &pages[cur_page], NULL);
-               up_read(&current->mm->mmap_sem);
-
+               ret = get_user_pages_fast(uaddr, local_nr_pages,
+                               write_to_vm, &pages[cur_page]);
                if (ret < local_nr_pages) {
                        ret = -EFAULT;
                        goto out_unmap;
@@ -758,19 +855,21 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
  *     @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)
+                        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);
+       return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm, gfp_mask);
 }
 
 /**
@@ -780,18 +879,19 @@ struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev,
  *     @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
  *
  *     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,
                             struct sg_iovec *iov, int iov_count,
-                            int write_to_vm)
+                            int write_to_vm, gfp_t gfp_mask)
 {
        struct bio *bio;
 
-       bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
-
+       bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm,
+                                gfp_mask);
        if (IS_ERR(bio))
                return bio;
 
@@ -915,19 +1015,22 @@ static void bio_copy_kern_endio(struct bio *bio, int err)
 {
        struct bio_vec *bvec;
        const int read = bio_data_dir(bio) == READ;
-       char *p = bio->bi_private;
+       struct bio_map_data *bmd = bio->bi_private;
        int i;
+       char *p = bmd->sgvecs[0].iov_base;
 
        __bio_for_each_segment(bvec, bio, i, 0) {
                char *addr = page_address(bvec->bv_page);
+               int len = bmd->iovecs[i].bv_len;
 
                if (read && !err)
-                       memcpy(p, addr, bvec->bv_len);
+                       memcpy(p, addr, len);
 
                __free_page(bvec->bv_page);
-               p += bvec->bv_len;
+               p += len;
        }
 
+       bio_free_map_data(bmd);
        bio_put(bio);
 }
 
@@ -945,38 +1048,13 @@ 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;
-       const int nr_pages = end - start;
        struct bio *bio;
        struct bio_vec *bvec;
-       int i, ret;
-
-       bio = bio_alloc(gfp_mask, nr_pages);
-       if (!bio)
-               return ERR_PTR(-ENOMEM);
-
-       while (len) {
-               struct page *page;
-               unsigned int bytes = PAGE_SIZE;
-
-               if (bytes > len)
-                       bytes = len;
-
-               page = alloc_page(q->bounce_gfp | gfp_mask);
-               if (!page) {
-                       ret = -ENOMEM;
-                       goto cleanup;
-               }
-
-               if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
-                       ret = -EINVAL;
-                       goto cleanup;
-               }
+       int i;
 
-               len -= bytes;
-       }
+       bio = bio_copy_user(q, NULL, (unsigned long)data, len, 1, gfp_mask);
+       if (IS_ERR(bio))
+               return bio;
 
        if (!reading) {
                void *p = data;
@@ -989,16 +1067,9 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
                }
        }
 
-       bio->bi_private = data;
        bio->bi_end_io = bio_copy_kern_endio;
-       return bio;
-cleanup:
-       bio_for_each_segment(bvec, bio, i)
-               __free_page(bvec->bv_page);
 
-       bio_put(bio);
-
-       return ERR_PTR(ret);
+       return bio;
 }
 
 /*
@@ -1185,9 +1256,9 @@ static void bio_pair_end_2(struct bio *bi, int err)
  * split a bio - only worry about a bio with a single page
  * in it's iovec
  */
-struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
+struct bio_pair *bio_split(struct bio *bi, int first_sectors)
 {
-       struct bio_pair *bp = mempool_alloc(pool, GFP_NOIO);
+       struct bio_pair *bp = mempool_alloc(bio_split_pool, GFP_NOIO);
 
        if (!bp)
                return bp;
@@ -1221,11 +1292,50 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
        bp->bio2.bi_end_io = bio_pair_end_2;
 
        bp->bio1.bi_private = bi;
-       bp->bio2.bi_private = pool;
+       bp->bio2.bi_private = bio_split_pool;
+
+       if (bio_integrity(bi))
+               bio_integrity_split(bi, bp, first_sectors);
 
        return bp;
 }
 
+/**
+ *      bio_sector_offset - Find hardware sector offset in bio
+ *      @bio:           bio to inspect
+ *      @index:         bio_vec index
+ *      @offset:        offset in bv_page
+ *
+ *      Return the number of hardware sectors between beginning of bio
+ *      and an end point indicated by a bio_vec index and an offset
+ *      within that vector's page.
+ */
+sector_t bio_sector_offset(struct bio *bio, unsigned short index,
+                          unsigned int offset)
+{
+       unsigned int sector_sz = queue_hardsect_size(bio->bi_bdev->bd_disk->queue);
+       struct bio_vec *bv;
+       sector_t sectors;
+       int i;
+
+       sectors = 0;
+
+       if (index >= bio->bi_idx)
+               index = bio->bi_vcnt - 1;
+
+       __bio_for_each_segment(bv, bio, i, 0) {
+               if (i == index) {
+                       if (offset > bv->bv_offset)
+                               sectors += (offset - bv->bv_offset) / sector_sz;
+                       break;
+               }
+
+               sectors += bv->bv_len / sector_sz;
+       }
+
+       return sectors;
+}
+EXPORT_SYMBOL(bio_sector_offset);
 
 /*
  * create memory pools for biovec's in a bio_set.
@@ -1264,6 +1374,7 @@ void bioset_free(struct bio_set *bs)
        if (bs->bio_pool)
                mempool_destroy(bs->bio_pool);
 
+       bioset_integrity_free(bs);
        biovec_free_pools(bs);
 
        kfree(bs);
@@ -1280,6 +1391,9 @@ struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size)
        if (!bs->bio_pool)
                goto bad;
 
+       if (bioset_integrity_create(bs, bio_pool_size))
+               goto bad;
+
        if (!biovec_create_pools(bs, bvec_pool_size))
                return bs;
 
@@ -1306,6 +1420,7 @@ static int __init init_bio(void)
 {
        bio_slab = KMEM_CACHE(bio, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
+       bio_integrity_init_slab();
        biovec_init_slabs();
 
        fs_bio_set = bioset_create(BIO_POOL_SIZE, 2);
@@ -1323,6 +1438,7 @@ static int __init init_bio(void)
 subsys_initcall(init_bio);
 
 EXPORT_SYMBOL(bio_alloc);
+EXPORT_SYMBOL(bio_kmalloc);
 EXPORT_SYMBOL(bio_put);
 EXPORT_SYMBOL(bio_free);
 EXPORT_SYMBOL(bio_endio);
@@ -1330,7 +1446,6 @@ EXPORT_SYMBOL(bio_init);
 EXPORT_SYMBOL(__bio_clone);
 EXPORT_SYMBOL(bio_clone);
 EXPORT_SYMBOL(bio_phys_segments);
-EXPORT_SYMBOL(bio_hw_segments);
 EXPORT_SYMBOL(bio_add_page);
 EXPORT_SYMBOL(bio_add_pc_page);
 EXPORT_SYMBOL(bio_get_nr_vecs);
@@ -1340,7 +1455,6 @@ EXPORT_SYMBOL(bio_map_kern);
 EXPORT_SYMBOL(bio_copy_kern);
 EXPORT_SYMBOL(bio_pair_release);
 EXPORT_SYMBOL(bio_split);
-EXPORT_SYMBOL(bio_split_pool);
 EXPORT_SYMBOL(bio_copy_user);
 EXPORT_SYMBOL(bio_uncopy_user);
 EXPORT_SYMBOL(bioset_create);