proc: less LOCK operations during lookup
[safe/jmp/linux-2.6] / fs / bio.c
index e49cf7d..242e409 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2001 Jens Axboe <axboe@kernel.dk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <linux/module.h>
 #include <linux/mempool.h>
 #include <linux/workqueue.h>
+#include <linux/blktrace_api.h>
 #include <scsi/sg.h>           /* for struct sg_iovec */
 
-#define BIO_POOL_SIZE 256
+#define BIO_POOL_SIZE 2
 
-static kmem_cache_t *bio_slab;
+static struct kmem_cache *bio_slab __read_mostly;
 
 #define BIOVEC_NR_POOLS 6
 
@@ -37,13 +38,13 @@ static kmem_cache_t *bio_slab;
  * a small number of entries is fine, not going to be performance critical.
  * basically we just need to survive
  */
-#define BIO_SPLIT_ENTRIES 8    
-mempool_t *bio_split_pool;
+#define BIO_SPLIT_ENTRIES 2
+mempool_t *bio_split_pool __read_mostly;
 
 struct biovec_slab {
        int nr_vecs;
        char *name; 
-       kmem_cache_t *slab;
+       struct kmem_cache *slab;
 };
 
 /*
@@ -75,10 +76,9 @@ struct bio_set {
  */
 static struct bio_set *fs_bio_set;
 
-static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
+static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
 {
        struct bio_vec *bvl;
-       struct biovec_slab *bp;
 
        /*
         * see comment near bvec_array define!
@@ -97,44 +97,42 @@ static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int
         * idx now points to the pool we want to allocate from
         */
 
-       bp = bvec_slabs + *idx;
        bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
-       if (bvl)
+       if (bvl) {
+               struct biovec_slab *bp = bvec_slabs + *idx;
+
                memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
+       }
 
        return bvl;
 }
 
+void bio_free(struct bio *bio, struct bio_set *bio_set)
+{
+       if (bio->bi_io_vec) {
+               const int pool_idx = BIO_POOL_IDX(bio);
+
+               BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
+
+               mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
+       }
+
+       mempool_free(bio, bio_set->bio_pool);
+}
+
 /*
  * default destructor for a bio allocated with bio_alloc_bioset()
  */
-static void bio_destructor(struct bio *bio)
+static void bio_fs_destructor(struct bio *bio)
 {
-       const int pool_idx = BIO_POOL_IDX(bio);
-       struct bio_set *bs = bio->bi_set;
-
-       BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
-
-       mempool_free(bio->bi_io_vec, bs->bvec_pools[pool_idx]);
-       mempool_free(bio, bs->bio_pool);
+       bio_free(bio, fs_bio_set);
 }
 
-inline void bio_init(struct bio *bio)
+void bio_init(struct bio *bio)
 {
-       bio->bi_next = NULL;
+       memset(bio, 0, sizeof(*bio));
        bio->bi_flags = 1 << BIO_UPTODATE;
-       bio->bi_rw = 0;
-       bio->bi_vcnt = 0;
-       bio->bi_idx = 0;
-       bio->bi_phys_segments = 0;
-       bio->bi_hw_segments = 0;
-       bio->bi_hw_front_size = 0;
-       bio->bi_hw_back_size = 0;
-       bio->bi_size = 0;
-       bio->bi_max_vecs = 0;
-       bio->bi_end_io = NULL;
        atomic_set(&bio->bi_cnt, 1);
-       bio->bi_private = NULL;
 }
 
 /**
@@ -151,7 +149,7 @@ inline void bio_init(struct bio *bio)
  *   allocate bio and iovecs from the memory pools specified by the
  *   bio_set structure.
  **/
-struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, struct bio_set *bs)
+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);
 
@@ -160,7 +158,7 @@ struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, stru
 
                bio_init(bio);
                if (likely(nr_iovecs)) {
-                       unsigned long idx;
+                       unsigned long idx = 0; /* shut up gcc */
 
                        bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
                        if (unlikely(!bvl)) {
@@ -172,16 +170,19 @@ struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, stru
                        bio->bi_max_vecs = bvec_slabs[idx].nr_vecs;
                }
                bio->bi_io_vec = bvl;
-               bio->bi_destructor = bio_destructor;
-               bio->bi_set = bs;
        }
 out:
        return bio;
 }
 
-struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs)
+struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
 {
-       return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+       struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+
+       if (bio)
+               bio->bi_destructor = bio_fs_destructor;
+
+       return bio;
 }
 
 void zero_fill_bio(struct bio *bio)
@@ -220,7 +221,7 @@ void bio_put(struct bio *bio)
        }
 }
 
-inline int bio_phys_segments(request_queue_t *q, struct bio *bio)
+inline int bio_phys_segments(struct request_queue *q, struct bio *bio)
 {
        if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
                blk_recount_segments(q, bio);
@@ -228,7 +229,7 @@ inline int bio_phys_segments(request_queue_t *q, struct bio *bio)
        return bio->bi_phys_segments;
 }
 
-inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
+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);
@@ -245,13 +246,15 @@ inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
  *     the actual data it points to. Reference count of returned
  *     bio will be one.
  */
-inline void __bio_clone(struct bio *bio, struct bio *bio_src)
+void __bio_clone(struct bio *bio, struct bio *bio_src)
 {
-       request_queue_t *q = bdev_get_queue(bio_src->bi_bdev);
-
        memcpy(bio->bi_io_vec, bio_src->bi_io_vec,
                bio_src->bi_max_vecs * sizeof(struct bio_vec));
 
+       /*
+        * most users will be overriding ->bi_bdev with a new target,
+        * so we don't set nor calculate new physical/hw segment counts here
+        */
        bio->bi_sector = bio_src->bi_sector;
        bio->bi_bdev = bio_src->bi_bdev;
        bio->bi_flags |= 1 << BIO_CLONED;
@@ -259,8 +262,6 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src)
        bio->bi_vcnt = bio_src->bi_vcnt;
        bio->bi_size = bio_src->bi_size;
        bio->bi_idx = bio_src->bi_idx;
-       bio_phys_segments(q, bio);
-       bio_hw_segments(q, bio);
 }
 
 /**
@@ -270,12 +271,14 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src)
  *
  *     Like __bio_clone, only also allocates the returned bio
  */
-struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask)
+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)
+       if (b) {
+               b->bi_destructor = bio_fs_destructor;
                __bio_clone(b, bio);
+       }
 
        return b;
 }
@@ -291,7 +294,7 @@ struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask)
  */
 int bio_get_nr_vecs(struct block_device *bdev)
 {
-       request_queue_t *q = bdev_get_queue(bdev);
+       struct request_queue *q = bdev_get_queue(bdev);
        int nr_pages;
 
        nr_pages = ((q->max_sectors << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -303,8 +306,9 @@ int bio_get_nr_vecs(struct block_device *bdev)
        return nr_pages;
 }
 
-static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
-                         *page, unsigned int len, unsigned int offset)
+static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
+                         *page, unsigned int len, unsigned int offset,
+                         unsigned short max_sectors)
 {
        int retried_segments = 0;
        struct bio_vec *bvec;
@@ -315,10 +319,31 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
        if (unlikely(bio_flagged(bio, BIO_CLONED)))
                return 0;
 
-       if (bio->bi_vcnt >= bio->bi_max_vecs)
+       if (((bio->bi_size + len) >> 9) > max_sectors)
                return 0;
 
-       if (((bio->bi_size + len) >> 9) > q->max_sectors)
+       /*
+        * For filesystems with a blocksize smaller than the pagesize
+        * we will often be called with the same page as last time and
+        * a consecutive offset.  Optimize this special case.
+        */
+       if (bio->bi_vcnt > 0) {
+               struct bio_vec *prev = &bio->bi_io_vec[bio->bi_vcnt - 1];
+
+               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;
+                       }
+
+                       goto done;
+               }
+       }
+
+       if (bio->bi_vcnt >= bio->bi_max_vecs)
                return 0;
 
        /*
@@ -372,11 +397,32 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
        bio->bi_vcnt++;
        bio->bi_phys_segments++;
        bio->bi_hw_segments++;
+ done:
        bio->bi_size += len;
        return len;
 }
 
 /**
+ *     bio_add_pc_page -       attempt to add page to bio
+ *     @q: the target queue
+ *     @bio: destination bio
+ *     @page: page to add
+ *     @len: vec entry length
+ *     @offset: vec entry offset
+ *
+ *     Attempt to add a page to the bio_vec maplist. This can fail for a
+ *     number of reasons, such as the bio being full or target block
+ *     device limitations. The target block device must allow bio's
+ *      smaller than PAGE_SIZE, so it is always possible to add a single
+ *      page to an empty bio. This should only be used by REQ_PC bios.
+ */
+int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page *page,
+                   unsigned int len, unsigned int offset)
+{
+       return __bio_add_page(q, bio, page, len, offset, q->max_hw_sectors);
+}
+
+/**
  *     bio_add_page    -       attempt to add page to bio
  *     @bio: destination bio
  *     @page: page to add
@@ -392,8 +438,8 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
 int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
                 unsigned int offset)
 {
-       return __bio_add_page(bdev_get_queue(bio->bi_bdev), bio, page,
-                             len, offset);
+       struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+       return __bio_add_page(q, bio, page, len, offset, q->max_sectors);
 }
 
 struct bio_map_data {
@@ -468,7 +514,7 @@ int bio_uncopy_user(struct bio *bio)
  *     to/from kernel pages as necessary. Must be paired with
  *     call bio_uncopy_user() on io completion.
  */
-struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
+struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
                          unsigned int len, int write_to_vm)
 {
        unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -505,10 +551,8 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
                        break;
                }
 
-               if (__bio_add_page(q, bio, page, bytes, 0) < bytes) {
-                       ret = -EINVAL;
+               if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
                        break;
-               }
 
                len -= bytes;
        }
@@ -547,7 +591,7 @@ out_bmd:
        return ERR_PTR(ret);
 }
 
-static struct bio *__bio_map_user_iov(request_queue_t *q,
+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)
@@ -567,10 +611,9 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
 
                nr_pages += end - start;
                /*
-                * transfer and buffer must be aligned to at least hardsector
-                * size for now, in the future we can relax this restriction
+                * buffer must be aligned to at least hardsector size for now
                 */
-               if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+               if (uaddr & queue_dma_alignment(q))
                        return ERR_PTR(-EINVAL);
        }
 
@@ -582,12 +625,10 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
                return ERR_PTR(-ENOMEM);
 
        ret = -ENOMEM;
-       pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+       pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
        if (!pages)
                goto out;
 
-       memset(pages, 0, nr_pages * sizeof(struct page *));
-
        for (i = 0; i < iov_count; i++) {
                unsigned long uaddr = (unsigned long)iov[i].iov_base;
                unsigned long len = iov[i].iov_len;
@@ -602,9 +643,10 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
                                     write_to_vm, 0, &pages[cur_page], NULL);
                up_read(&current->mm->mmap_sem);
 
-               if (ret < local_nr_pages)
+               if (ret < local_nr_pages) {
+                       ret = -EFAULT;
                        goto out_unmap;
-
+               }
 
                offset = uaddr & ~PAGE_MASK;
                for (j = cur_page; j < page_limit; j++) {
@@ -619,7 +661,8 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
                        /*
                         * sorry...
                         */
-                       if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes)
+                       if (bio_add_pc_page(q, bio, pages[j], bytes, offset) <
+                                           bytes)
                                break;
 
                        len -= bytes;
@@ -660,7 +703,7 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
 
 /**
  *     bio_map_user    -       map user address into bio
- *     @q: the request_queue_t for the bio
+ *     @q: the struct request_queue for the bio
  *     @bdev: destination block device
  *     @uaddr: start of user address
  *     @len: length in bytes
@@ -669,12 +712,12 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
  *     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(request_queue_t *q, struct block_device *bdev,
+struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev,
                         unsigned long uaddr, unsigned int len, int write_to_vm)
 {
        struct sg_iovec iov;
 
-       iov.iov_base = (__user void *)uaddr;
+       iov.iov_base = (void __user *)uaddr;
        iov.iov_len = len;
 
        return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm);
@@ -682,7 +725,7 @@ struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
 
 /**
  *     bio_map_user_iov - map user sg_iovec table into bio
- *     @q: the request_queue_t for the bio
+ *     @q: the struct request_queue for the bio
  *     @bdev: destination block device
  *     @iov:   the iovec.
  *     @iov_count: number of elements in the iovec
@@ -691,12 +734,11 @@ struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
  *     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(request_queue_t *q, struct block_device *bdev,
+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)
 {
        struct bio *bio;
-       int len = 0, i;
 
        bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
 
@@ -711,18 +753,7 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
         */
        bio_get(bio);
 
-       for (i = 0; i < iov_count; i++)
-               len += iov[i].iov_len;
-
-       if (bio->bi_size == len)
-               return bio;
-
-       /*
-        * don't support partial mappings
-        */
-       bio_endio(bio, bio->bi_size, 0);
-       bio_unmap_user(bio);
-       return ERR_PTR(-EINVAL);
+       return bio;
 }
 
 static void __bio_unmap_user(struct bio *bio)
@@ -758,18 +789,14 @@ void bio_unmap_user(struct bio *bio)
        bio_put(bio);
 }
 
-static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err)
+static void bio_map_kern_endio(struct bio *bio, int err)
 {
-       if (bio->bi_size)
-               return 1;
-
        bio_put(bio);
-       return 0;
 }
 
 
-static struct bio *__bio_map_kern(request_queue_t *q, void *data,
-                                 unsigned int len, unsigned int gfp_mask)
+static struct bio *__bio_map_kern(struct request_queue *q, void *data,
+                                 unsigned int len, gfp_t gfp_mask)
 {
        unsigned long kaddr = (unsigned long)data;
        unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -792,8 +819,8 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data,
                if (bytes > len)
                        bytes = len;
 
-               if (__bio_add_page(q, bio, virt_to_page(data), bytes,
-                                  offset) < bytes)
+               if (bio_add_pc_page(q, bio, virt_to_page(data), bytes,
+                                   offset) < bytes)
                        break;
 
                data += bytes;
@@ -807,7 +834,7 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data,
 
 /**
  *     bio_map_kern    -       map kernel address into bio
- *     @q: the request_queue_t for the bio
+ *     @q: the struct request_queue for the bio
  *     @data: pointer to buffer to map
  *     @len: length in bytes
  *     @gfp_mask: allocation flags for bio allocation
@@ -815,8 +842,8 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data,
  *     Map the kernel address into a bio suitable for io to a block
  *     device. Returns an error pointer in case of error.
  */
-struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len,
-                        unsigned int gfp_mask)
+struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
+                        gfp_t gfp_mask)
 {
        struct bio *bio;
 
@@ -876,7 +903,7 @@ void bio_set_pages_dirty(struct bio *bio)
        }
 }
 
-static void bio_release_pages(struct bio *bio)
+void bio_release_pages(struct bio *bio)
 {
        struct bio_vec *bvec = bio->bi_io_vec;
        int i;
@@ -900,16 +927,16 @@ static void bio_release_pages(struct bio *bio)
  * run one bio_put() against the BIO.
  */
 
-static void bio_dirty_fn(void *data);
+static void bio_dirty_fn(struct work_struct *work);
 
-static DECLARE_WORK(bio_dirty_work, bio_dirty_fn, NULL);
+static DECLARE_WORK(bio_dirty_work, bio_dirty_fn);
 static DEFINE_SPINLOCK(bio_dirty_lock);
 static struct bio *bio_dirty_list;
 
 /*
  * This runs in process context
  */
-static void bio_dirty_fn(void *data)
+static void bio_dirty_fn(struct work_struct *work)
 {
        unsigned long flags;
        struct bio *bio;
@@ -962,34 +989,26 @@ void bio_check_pages_dirty(struct bio *bio)
 /**
  * bio_endio - end I/O on a bio
  * @bio:       bio
- * @bytes_done:        number of bytes completed
  * @error:     error, if any
  *
  * Description:
- *   bio_endio() will end I/O on @bytes_done number of bytes. This may be
- *   just a partial part of the bio, or it may be the whole bio. bio_endio()
- *   is the preferred way to end I/O on a bio, it takes care of decrementing
- *   bi_size and clearing BIO_UPTODATE on error. @error is 0 on success, and
- *   and one of the established -Exxxx (-EIO, for instance) error values in
- *   case something went wrong. Noone should call bi_end_io() directly on
- *   a bio unless they own it and thus know that it has an end_io function.
+ *   bio_endio() will end I/O on the whole bio. bio_endio() is the
+ *   preferred way to end I/O on a bio, it takes care of clearing
+ *   BIO_UPTODATE on error. @error is 0 on success, and and one of the
+ *   established -Exxxx (-EIO, for instance) error values in case
+ *   something went wrong. Noone should call bi_end_io() directly on a
+ *   bio unless they own it and thus know that it has an end_io
+ *   function.
  **/
-void bio_endio(struct bio *bio, unsigned int bytes_done, int error)
+void bio_endio(struct bio *bio, int error)
 {
        if (error)
                clear_bit(BIO_UPTODATE, &bio->bi_flags);
-
-       if (unlikely(bytes_done > bio->bi_size)) {
-               printk("%s: want %u bytes done, only %u left\n", __FUNCTION__,
-                                               bytes_done, bio->bi_size);
-               bytes_done = bio->bi_size;
-       }
-
-       bio->bi_size -= bytes_done;
-       bio->bi_sector += (bytes_done >> 9);
+       else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+               error = -EIO;
 
        if (bio->bi_end_io)
-               bio->bi_end_io(bio, bytes_done, error);
+               bio->bi_end_io(bio, error);
 }
 
 void bio_pair_release(struct bio_pair *bp)
@@ -997,37 +1016,29 @@ void bio_pair_release(struct bio_pair *bp)
        if (atomic_dec_and_test(&bp->cnt)) {
                struct bio *master = bp->bio1.bi_private;
 
-               bio_endio(master, master->bi_size, bp->error);
+               bio_endio(master, bp->error);
                mempool_free(bp, bp->bio2.bi_private);
        }
 }
 
-static int bio_pair_end_1(struct bio * bi, unsigned int done, int err)
+static void bio_pair_end_1(struct bio *bi, int err)
 {
        struct bio_pair *bp = container_of(bi, struct bio_pair, bio1);
 
        if (err)
                bp->error = err;
 
-       if (bi->bi_size)
-               return 1;
-
        bio_pair_release(bp);
-       return 0;
 }
 
-static int bio_pair_end_2(struct bio * bi, unsigned int done, int err)
+static void bio_pair_end_2(struct bio *bi, int err)
 {
        struct bio_pair *bp = container_of(bi, struct bio_pair, bio2);
 
        if (err)
                bp->error = err;
 
-       if (bi->bi_size)
-               return 1;
-
        bio_pair_release(bp);
-       return 0;
 }
 
 /*
@@ -1041,6 +1052,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
        if (!bp)
                return bp;
 
+       blk_add_trace_pdu_int(bdev_get_queue(bi->bi_bdev), BLK_TA_SPLIT, bi,
+                               bi->bi_sector + first_sectors);
+
        BUG_ON(bi->bi_vcnt != 1);
        BUG_ON(bi->bi_idx != 0);
        atomic_set(&bp->cnt, 3);
@@ -1060,6 +1074,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
        bp->bio1.bi_io_vec = &bp->bv1;
        bp->bio2.bi_io_vec = &bp->bv2;
 
+       bp->bio1.bi_max_vecs = 1;
+       bp->bio2.bi_max_vecs = 1;
+
        bp->bio1.bi_end_io = bio_pair_end_1;
        bp->bio2.bi_end_io = bio_pair_end_2;
 
@@ -1069,22 +1086,12 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
        return bp;
 }
 
-static void *bio_pair_alloc(unsigned int __nocast gfp_flags, void *data)
-{
-       return kmalloc(sizeof(struct bio_pair), gfp_flags);
-}
-
-static void bio_pair_free(void *bp, void *data)
-{
-       kfree(bp);
-}
-
 
 /*
  * create memory pools for biovec's in a bio_set.
  * use the global biovec slabs created for general use.
  */
-static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale)
+static int biovec_create_pools(struct bio_set *bs, int pool_entries)
 {
        int i;
 
@@ -1092,11 +1099,7 @@ static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale)
                struct biovec_slab *bp = bvec_slabs + i;
                mempool_t **bvp = bs->bvec_pools + i;
 
-               if (i >= scale)
-                       pool_entries >>= 1;
-
-               *bvp = mempool_create(pool_entries, mempool_alloc_slab,
-                                       mempool_free_slab, bp->slab);
+               *bvp = mempool_create_slab_pool(pool_entries, bp->slab);
                if (!*bvp)
                        return -ENOMEM;
        }
@@ -1126,21 +1129,18 @@ void bioset_free(struct bio_set *bs)
        kfree(bs);
 }
 
-struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size, int scale)
+struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size)
 {
-       struct bio_set *bs = kmalloc(sizeof(*bs), GFP_KERNEL);
+       struct bio_set *bs = kzalloc(sizeof(*bs), GFP_KERNEL);
 
        if (!bs)
                return NULL;
 
-       memset(bs, 0, sizeof(*bs));
-       bs->bio_pool = mempool_create(bio_pool_size, mempool_alloc_slab,
-                       mempool_free_slab, bio_slab);
-
+       bs->bio_pool = mempool_create_slab_pool(bio_pool_size, bio_slab);
        if (!bs->bio_pool)
                goto bad;
 
-       if (!biovec_create_pools(bs, bvec_pool_size, scale))
+       if (!biovec_create_pools(bs, bvec_pool_size))
                return bs;
 
 bad:
@@ -1158,49 +1158,22 @@ static void __init biovec_init_slabs(void)
 
                size = bvs->nr_vecs * sizeof(struct bio_vec);
                bvs->slab = kmem_cache_create(bvs->name, size, 0,
-                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
        }
 }
 
 static int __init init_bio(void)
 {
-       int megabytes, bvec_pool_entries;
-       int scale = BIOVEC_NR_POOLS;
-
-       bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
-                               SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       bio_slab = KMEM_CACHE(bio, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        biovec_init_slabs();
 
-       megabytes = nr_free_pages() >> (20 - PAGE_SHIFT);
-
-       /*
-        * find out where to start scaling
-        */
-       if (megabytes <= 16)
-               scale = 0;
-       else if (megabytes <= 32)
-               scale = 1;
-       else if (megabytes <= 64)
-               scale = 2;
-       else if (megabytes <= 96)
-               scale = 3;
-       else if (megabytes <= 128)
-               scale = 4;
-
-       /*
-        * scale number of entries
-        */
-       bvec_pool_entries = megabytes * 2;
-       if (bvec_pool_entries > 256)
-               bvec_pool_entries = 256;
-
-       fs_bio_set = bioset_create(BIO_POOL_SIZE, bvec_pool_entries, scale);
+       fs_bio_set = bioset_create(BIO_POOL_SIZE, 2);
        if (!fs_bio_set)
                panic("bio: can't allocate bios\n");
 
-       bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES,
-                               bio_pair_alloc, bio_pair_free, NULL);
+       bio_split_pool = mempool_create_kmalloc_pool(BIO_SPLIT_ENTRIES,
+                                                    sizeof(struct bio_pair));
        if (!bio_split_pool)
                panic("bio: can't create split pool\n");
 
@@ -1211,6 +1184,7 @@ subsys_initcall(init_bio);
 
 EXPORT_SYMBOL(bio_alloc);
 EXPORT_SYMBOL(bio_put);
+EXPORT_SYMBOL(bio_free);
 EXPORT_SYMBOL(bio_endio);
 EXPORT_SYMBOL(bio_init);
 EXPORT_SYMBOL(__bio_clone);
@@ -1218,9 +1192,8 @@ 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);
-EXPORT_SYMBOL(bio_map_user);
-EXPORT_SYMBOL(bio_unmap_user);
 EXPORT_SYMBOL(bio_map_kern);
 EXPORT_SYMBOL(bio_pair_release);
 EXPORT_SYMBOL(bio_split);