fix mismerge in ll_rw_blk.c
authorJames Bottomley <jejb@titanic.(none)>
Sun, 28 Aug 2005 15:43:07 +0000 (10:43 -0500)
committerJames Bottomley <jejb@titanic.(none)>
Sun, 28 Aug 2005 15:43:07 +0000 (10:43 -0500)
1  2 
drivers/block/ll_rw_blk.c
drivers/ide/ide-disk.c
fs/bio.c
include/linux/bio.h
include/linux/blkdev.h

index 3c818544475ea857d249f1afc8f259028c163a2b,f6fda036b4aefb19677e08130d1a877ba8dd8a84..0c7599563b651448a800eb4d19ccd330bcb4edee
@@@ -28,7 -28,6 +28,7 @@@
  #include <linux/slab.h>
  #include <linux/swap.h>
  #include <linux/writeback.h>
 +#include <linux/blkdev.h>
  
  /*
   * for max sense size
@@@ -37,7 -36,6 +37,7 @@@
  
  static void blk_unplug_work(void *data);
  static void blk_unplug_timeout(unsigned long data);
 +static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
  
  /*
   * For the allocated request tables
@@@ -276,7 -274,6 +276,7 @@@ static inline void rq_init(request_queu
        rq->errors = 0;
        rq->rq_status = RQ_ACTIVE;
        rq->bio = rq->biotail = NULL;
 +      rq->ioprio = 0;
        rq->buffer = NULL;
        rq->ref_count = 1;
        rq->q = q;
        rq->special = NULL;
        rq->data_len = 0;
        rq->data = NULL;
+       rq->nr_phys_segments = 0;
        rq->sense = NULL;
        rq->end_io = NULL;
        rq->end_io_data = NULL;
@@@ -777,9 -775,9 +778,9 @@@ EXPORT_SYMBOL(blk_queue_free_tags)
  static int
  init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
  {
 -      int bits, i;
        struct request **tag_index;
        unsigned long *tag_map;
 +      int nr_ulongs;
  
        if (depth > q->nr_requests * 2) {
                depth = q->nr_requests * 2;
        if (!tag_index)
                goto fail;
  
 -      bits = (depth / BLK_TAGS_PER_LONG) + 1;
 -      tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
 +      nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
 +      tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
        if (!tag_map)
                goto fail;
  
        memset(tag_index, 0, depth * sizeof(struct request *));
 -      memset(tag_map, 0, bits * sizeof(unsigned long));
 +      memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
 +      tags->real_max_depth = depth;
        tags->max_depth = depth;
 -      tags->real_max_depth = bits * BITS_PER_LONG;
        tags->tag_index = tag_index;
        tags->tag_map = tag_map;
  
 -      /*
 -       * set the upper bits if the depth isn't a multiple of the word size
 -       */
 -      for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
 -              __set_bit(i, tag_map);
 -
        return 0;
  fail:
        kfree(tag_index);
@@@ -867,16 -871,13 +868,16 @@@ int blk_queue_resize_tags(request_queue
        struct blk_queue_tag *bqt = q->queue_tags;
        struct request **tag_index;
        unsigned long *tag_map;
 -      int bits, max_depth;
 +      int max_depth, nr_ulongs;
  
        if (!bqt)
                return -ENXIO;
  
        /*
 -       * don't bother sizing down
 +       * if we already have large enough real_max_depth.  just
 +       * adjust max_depth.  *NOTE* as requests with tag value
 +       * between new_depth and real_max_depth can be in-flight, tag
 +       * map can not be shrunk blindly here.
         */
        if (new_depth <= bqt->real_max_depth) {
                bqt->max_depth = new_depth;
                return -ENOMEM;
  
        memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
 -      bits = max_depth / BLK_TAGS_PER_LONG;
 -      memcpy(bqt->tag_map, tag_map, bits * sizeof(unsigned long));
 +      nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG;
 +      memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long));
  
        kfree(tag_index);
        kfree(tag_map);
@@@ -926,15 -927,10 +927,15 @@@ void blk_queue_end_tag(request_queue_t 
        BUG_ON(tag == -1);
  
        if (unlikely(tag >= bqt->real_max_depth))
 +              /*
 +               * This can happen after tag depth has been reduced.
 +               * FIXME: how about a warning or info message here?
 +               */
                return;
  
        if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
 -              printk("attempt to clear non-busy tag (%d)\n", tag);
 +              printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
 +                     __FUNCTION__, tag);
                return;
        }
  
        rq->tag = -1;
  
        if (unlikely(bqt->tag_index[tag] == NULL))
 -              printk("tag %d is missing\n", tag);
 +              printk(KERN_ERR "%s: tag %d is missing\n",
 +                     __FUNCTION__, tag);
  
        bqt->tag_index[tag] = NULL;
        bqt->busy--;
@@@ -973,20 -968,24 +974,20 @@@ EXPORT_SYMBOL(blk_queue_end_tag)
  int blk_queue_start_tag(request_queue_t *q, struct request *rq)
  {
        struct blk_queue_tag *bqt = q->queue_tags;
 -      unsigned long *map = bqt->tag_map;
 -      int tag = 0;
 +      int tag;
  
        if (unlikely((rq->flags & REQ_QUEUED))) {
                printk(KERN_ERR 
 -                     "request %p for device [%s] already tagged %d",
 -                     rq, rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
 +                     "%s: request %p for device [%s] already tagged %d",
 +                     __FUNCTION__, rq,
 +                     rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
                BUG();
        }
  
 -      for (map = bqt->tag_map; *map == -1UL; map++) {
 -              tag += BLK_TAGS_PER_LONG;
 -
 -              if (tag >= bqt->max_depth)
 -                      return 1;
 -      }
 +      tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
 +      if (tag >= bqt->max_depth)
 +              return 1;
  
 -      tag += ffz(*map);
        __set_bit(tag, bqt->tag_map);
  
        rq->flags |= REQ_QUEUED;
@@@ -1022,8 -1021,7 +1023,8 @@@ void blk_queue_invalidate_tags(request_
                rq = list_entry_rq(tmp);
  
                if (rq->tag == -1) {
 -                      printk("bad tag found on list\n");
 +                      printk(KERN_ERR
 +                             "%s: bad tag found on list\n", __FUNCTION__);
                        list_del_init(&rq->queuelist);
                        rq->flags &= ~REQ_QUEUED;
                } else
@@@ -1151,7 -1149,7 +1152,7 @@@ new_hw_segment
  }
  
  
 -int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
 +static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
                                   struct bio *nxt)
  {
        if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
        return 0;
  }
  
 -EXPORT_SYMBOL(blk_phys_contig_segment);
 -
 -int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
 +static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
                                 struct bio *nxt)
  {
        if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
        return 1;
  }
  
 -EXPORT_SYMBOL(blk_hw_contig_segment);
 -
  /*
   * map a request to scatterlist, return number of sg entries setup. Caller
   * must make sure sg can hold rq->nr_phys_segments entries
@@@ -1357,8 -1359,8 +1358,8 @@@ static int ll_front_merge_fn(request_qu
  static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
                                struct request *next)
  {
 -      int total_phys_segments = req->nr_phys_segments +next->nr_phys_segments;
 -      int total_hw_segments = req->nr_hw_segments + next->nr_hw_segments;
 +      int total_phys_segments;
 +      int total_hw_segments;
  
        /*
         * First check if the either of the requests are re-queued
                return 0;
  
        /*
 -       * Will it become to large?
 +       * Will it become too large?
         */
        if ((req->nr_sectors + next->nr_sectors) > q->max_sectors)
                return 0;
@@@ -1449,13 -1451,17 +1450,13 @@@ EXPORT_SYMBOL(blk_remove_plug)
   */
  void __generic_unplug_device(request_queue_t *q)
  {
 -      if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
 +      if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
                return;
  
        if (!blk_remove_plug(q))
                return;
  
 -      /*
 -       * was plugged, fire request_fn if queue has stuff to do
 -       */
 -      if (elv_next_request(q))
 -              q->request_fn(q);
 +      q->request_fn(q);
  }
  EXPORT_SYMBOL(__generic_unplug_device);
  
@@@ -1640,8 -1646,7 +1641,8 @@@ static int blk_init_free_list(request_q
        init_waitqueue_head(&rl->wait[WRITE]);
        init_waitqueue_head(&rl->drain);
  
 -      rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep);
 +      rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
 +                              mempool_free_slab, request_cachep, q->node);
  
        if (!rl->rq_pool)
                return -ENOMEM;
@@@ -1653,15 -1658,8 +1654,15 @@@ static int __make_request(request_queue
  
  request_queue_t *blk_alloc_queue(int gfp_mask)
  {
 -      request_queue_t *q = kmem_cache_alloc(requestq_cachep, gfp_mask);
 +      return blk_alloc_queue_node(gfp_mask, -1);
 +}
 +EXPORT_SYMBOL(blk_alloc_queue);
 +
 +request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
 +{
 +      request_queue_t *q;
  
 +      q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
        if (!q)
                return NULL;
  
  
        return q;
  }
 -
 -EXPORT_SYMBOL(blk_alloc_queue);
 +EXPORT_SYMBOL(blk_alloc_queue_node);
  
  /**
   * blk_init_queue  - prepare a request queue for use with a block device
   *    blk_init_queue() must be paired with a blk_cleanup_queue() call
   *    when the block device is deactivated (such as at module unload).
   **/
 +
  request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
  {
 -      request_queue_t *q = blk_alloc_queue(GFP_KERNEL);
 +      return blk_init_queue_node(rfn, lock, -1);
 +}
 +EXPORT_SYMBOL(blk_init_queue);
 +
 +request_queue_t *
 +blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
 +{
 +      request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
  
        if (!q)
                return NULL;
  
 +      q->node = node_id;
        if (blk_init_free_list(q))
                goto out_init;
  
@@@ -1765,11 -1755,12 +1766,11 @@@ out_init
        kmem_cache_free(requestq_cachep, q);
        return NULL;
  }
 -
 -EXPORT_SYMBOL(blk_init_queue);
 +EXPORT_SYMBOL(blk_init_queue_node);
  
  int blk_get_queue(request_queue_t *q)
  {
 -      if (!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
 +      if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
                atomic_inc(&q->refcnt);
                return 0;
        }
@@@ -1785,8 -1776,8 +1786,8 @@@ static inline void blk_free_request(req
        mempool_free(rq, q->rq.rq_pool);
  }
  
 -static inline struct request *blk_alloc_request(request_queue_t *q, int rw,
 -                                              int gfp_mask)
 +static inline struct request *
 +blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
  {
        struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
  
         */
        rq->flags = rw;
  
 -      if (!elv_set_request(q, rq, gfp_mask))
 +      if (!elv_set_request(q, rq, bio, gfp_mask))
                return rq;
  
        mempool_free(rq, q->rq.rq_pool);
@@@ -1831,7 -1822,7 +1832,7 @@@ static inline int ioc_batching(request_
   * is the behaviour we want though - once it gets a wakeup it should be given
   * a nice run.
   */
 -void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
 +static void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
  {
        if (!ioc || ioc_batching(q, ioc))
                return;
@@@ -1848,6 -1839,7 +1849,6 @@@ static void __freed_request(request_que
                clear_queue_congested(q, rw);
  
        if (rl->count[rw] + 1 <= q->nr_requests) {
 -              smp_mb();
                if (waitqueue_active(&rl->wait[rw]))
                        wake_up(&rl->wait[rw]);
  
@@@ -1879,20 -1871,18 +1880,20 @@@ static void freed_request(request_queue
  
  #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
  /*
 - * Get a free request, queue_lock must not be held
 + * Get a free request, queue_lock must be held.
 + * Returns NULL on failure, with queue_lock held.
 + * Returns !NULL on success, with queue_lock *not held*.
   */
 -static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
 +static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
 +                                 int gfp_mask)
  {
        struct request *rq = NULL;
        struct request_list *rl = &q->rq;
 -      struct io_context *ioc = get_io_context(gfp_mask);
 +      struct io_context *ioc = current_io_context(GFP_ATOMIC);
  
        if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
                goto out;
  
 -      spin_lock_irq(q->queue_lock);
        if (rl->count[rw]+1 >= q->nr_requests) {
                /*
                 * The queue will fill after this allocation, so set it as
                }
        }
  
 -      switch (elv_may_queue(q, rw)) {
 +      switch (elv_may_queue(q, rw, bio)) {
                case ELV_MQUEUE_NO:
                        goto rq_starved;
                case ELV_MQUEUE_MAY:
                 * The queue is full and the allocating process is not a
                 * "batcher", and not exempted by the IO scheduler
                 */
 -              spin_unlock_irq(q->queue_lock);
                goto out;
        }
  
  get_rq:
 +      /*
 +       * Only allow batching queuers to allocate up to 50% over the defined
 +       * limit of requests, otherwise we could have thousands of requests
 +       * allocated with any setting of ->nr_requests
 +       */
 +      if (rl->count[rw] >= (3 * q->nr_requests / 2))
 +              goto out;
 +
        rl->count[rw]++;
        rl->starved[rw] = 0;
        if (rl->count[rw] >= queue_congestion_on_threshold(q))
                set_queue_congested(q, rw);
        spin_unlock_irq(q->queue_lock);
  
 -      rq = blk_alloc_request(q, rw, gfp_mask);
 +      rq = blk_alloc_request(q, rw, bio, gfp_mask);
        if (!rq) {
                /*
                 * Allocation failed presumably due to memory. Undo anything
@@@ -1961,6 -1944,7 +1962,6 @@@ rq_starved
                if (unlikely(rl->count[rw] == 0))
                        rl->starved[rw] = 1;
  
 -              spin_unlock_irq(q->queue_lock);
                goto out;
        }
  
        rq_init(q, rq);
        rq->rl = rl;
  out:
 -      put_io_context(ioc);
        return rq;
  }
  
  /*
   * No available requests for this queue, unplug the device and wait for some
   * requests to become available.
 + *
 + * Called with q->queue_lock held, and returns with it unlocked.
   */
 -static struct request *get_request_wait(request_queue_t *q, int rw)
 +static struct request *get_request_wait(request_queue_t *q, int rw,
 +                                      struct bio *bio)
  {
 -      DEFINE_WAIT(wait);
        struct request *rq;
  
 -      generic_unplug_device(q);
 -      do {
 +      rq = get_request(q, rw, bio, GFP_NOIO);
 +      while (!rq) {
 +              DEFINE_WAIT(wait);
                struct request_list *rl = &q->rq;
  
                prepare_to_wait_exclusive(&rl->wait[rw], &wait,
                                TASK_UNINTERRUPTIBLE);
  
 -              rq = get_request(q, rw, GFP_NOIO);
 +              rq = get_request(q, rw, bio, GFP_NOIO);
  
                if (!rq) {
                        struct io_context *ioc;
  
 +                      __generic_unplug_device(q);
 +                      spin_unlock_irq(q->queue_lock);
                        io_schedule();
  
                        /*
                         * up to a big batch of them for a small period time.
                         * See ioc_batching, ioc_set_batching
                         */
 -                      ioc = get_io_context(GFP_NOIO);
 +                      ioc = current_io_context(GFP_NOIO);
                        ioc_set_batching(q, ioc);
 -                      put_io_context(ioc);
 +
 +                      spin_lock_irq(q->queue_lock);
                }
                finish_wait(&rl->wait[rw], &wait);
 -      } while (!rq);
 +      }
  
        return rq;
  }
@@@ -2024,18 -2003,14 +2025,18 @@@ struct request *blk_get_request(request
  
        BUG_ON(rw != READ && rw != WRITE);
  
 -      if (gfp_mask & __GFP_WAIT)
 -              rq = get_request_wait(q, rw);
 -      else
 -              rq = get_request(q, rw, gfp_mask);
 +      spin_lock_irq(q->queue_lock);
 +      if (gfp_mask & __GFP_WAIT) {
 +              rq = get_request_wait(q, rw, NULL);
 +      } else {
 +              rq = get_request(q, rw, NULL, gfp_mask);
 +              if (!rq)
 +                      spin_unlock_irq(q->queue_lock);
 +      }
 +      /* q->queue_lock is unlocked at this point */
  
        return rq;
  }
 -
  EXPORT_SYMBOL(blk_get_request);
  
  /**
@@@ -2115,7 -2090,7 +2116,7 @@@ EXPORT_SYMBOL(blk_insert_request)
  /**
   * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage
   * @q:                request queue where request should be inserted
-  * @rw:               READ or WRITE data
+  * @rq:               request structure to fill
   * @ubuf:     the user buffer
   * @len:      length of user data
   *
   *    original bio must be passed back in to blk_rq_unmap_user() for proper
   *    unmapping.
   */
struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
-                               unsigned int len)
int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
+                   unsigned int len)
  {
        unsigned long uaddr;
-       struct request *rq;
        struct bio *bio;
+       int reading;
  
        if (len > (q->max_sectors << 9))
-               return ERR_PTR(-EINVAL);
-       if ((!len && ubuf) || (len && !ubuf))
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
+       if (!len || !ubuf)
+               return -EINVAL;
  
-       rq = blk_get_request(q, rw, __GFP_WAIT);
-       if (!rq)
-               return ERR_PTR(-ENOMEM);
+       reading = rq_data_dir(rq) == READ;
  
        /*
         * if alignment requirement is satisfied, map in user pages for
         */
        uaddr = (unsigned long) ubuf;
        if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
-               bio = bio_map_user(q, NULL, uaddr, len, rw == READ);
+               bio = bio_map_user(q, NULL, uaddr, len, reading);
        else
-               bio = bio_copy_user(q, uaddr, len, rw == READ);
+               bio = bio_copy_user(q, uaddr, len, reading);
  
        if (!IS_ERR(bio)) {
                rq->bio = rq->biotail = bio;
  
                rq->buffer = rq->data = NULL;
                rq->data_len = len;
-               return rq;
+               return 0;
        }
  
        /*
         * bio is the err-ptr
         */
-       blk_put_request(rq);
-       return (struct request *) bio;
+       return PTR_ERR(bio);
  }
  
  EXPORT_SYMBOL(blk_rq_map_user);
  
+ /**
+  * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage
+  * @q:                request queue where request should be inserted
+  * @rq:               request to map data to
+  * @iov:      pointer to the iovec
+  * @iov_count:        number of elements in the iovec
+  *
+  * Description:
+  *    Data will be mapped directly for zero copy io, if possible. Otherwise
+  *    a kernel bounce buffer is used.
+  *
+  *    A matching blk_rq_unmap_user() must be issued at the end of io, while
+  *    still in process context.
+  *
+  *    Note: The mapped bio may need to be bounced through blk_queue_bounce()
+  *    before being submitted to the device, as pages mapped may be out of
+  *    reach. It's the callers responsibility to make sure this happens. The
+  *    original bio must be passed back in to blk_rq_unmap_user() for proper
+  *    unmapping.
+  */
+ int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
+                       struct sg_iovec *iov, int iov_count)
+ {
+       struct bio *bio;
+       if (!iov || iov_count <= 0)
+               return -EINVAL;
+       /* we don't allow misaligned data like bio_map_user() does.  If the
+        * user is using sg, they're expected to know the alignment constraints
+        * and respect them accordingly */
+       bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ);
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
+       rq->bio = rq->biotail = bio;
+       blk_rq_bio_prep(q, rq, bio);
+       rq->buffer = rq->data = NULL;
+       rq->data_len = bio->bi_size;
+       return 0;
+ }
+ EXPORT_SYMBOL(blk_rq_map_user_iov);
  /**
   * blk_rq_unmap_user - unmap a request with user data
-  * @rq:               request to be unmapped
-  * @bio:      bio for the request
+  * @bio:      bio to be unmapped
   * @ulen:     length of user buffer
   *
   * Description:
-  *    Unmap a request previously mapped by blk_rq_map_user().
+  *    Unmap a bio previously mapped by blk_rq_map_user().
   */
- int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
+ int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
  {
        int ret = 0;
  
                        ret = bio_uncopy_user(bio);
        }
  
-       blk_put_request(rq);
-       return ret;
+       return 0;
  }
  
  EXPORT_SYMBOL(blk_rq_unmap_user);
  
+ /**
+  * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage
+  * @q:                request queue where request should be inserted
+  * @rq:               request to fill
+  * @kbuf:     the kernel buffer
+  * @len:      length of user data
+  * @gfp_mask: memory allocation flags
+  */
+ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+                   unsigned int len, unsigned int gfp_mask)
+ {
+       struct bio *bio;
+       if (len > (q->max_sectors << 9))
+               return -EINVAL;
+       if (!len || !kbuf)
+               return -EINVAL;
+       bio = bio_map_kern(q, kbuf, len, gfp_mask);
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
+       if (rq_data_dir(rq) == WRITE)
+               bio->bi_rw |= (1 << BIO_RW);
+       rq->bio = rq->biotail = bio;
+       blk_rq_bio_prep(q, rq, bio);
+       rq->buffer = rq->data = NULL;
+       rq->data_len = len;
+       return 0;
+ }
+ EXPORT_SYMBOL(blk_rq_map_kern);
+ /**
+  * blk_execute_rq_nowait - insert a request into queue for execution
+  * @q:                queue to insert the request in
+  * @bd_disk:  matching gendisk
+  * @rq:               request to insert
+  * @at_head:    insert request at head or tail of queue
+  * @done:     I/O completion handler
+  *
+  * Description:
+  *    Insert a fully prepared request at the back of the io scheduler queue
+  *    for execution.  Don't wait for completion.
+  */
+ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
+                          struct request *rq, int at_head,
+                          void (*done)(struct request *))
+ {
+       int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+       rq->rq_disk = bd_disk;
+       rq->flags |= REQ_NOMERGE;
+       rq->end_io = done;
+       elv_add_request(q, rq, where, 1);
+       generic_unplug_device(q);
+ }
  /**
   * blk_execute_rq - insert a request into queue for execution
   * @q:                queue to insert the request in
   * @bd_disk:  matching gendisk
   * @rq:               request to insert
+  * @at_head:    insert request at head or tail of queue
   *
   * Description:
   *    Insert a fully prepared request at the back of the io scheduler queue
-  *    for execution.
+  *    for execution and wait for completion.
   */
  int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
-                  struct request *rq)
+                  struct request *rq, int at_head)
  {
        DECLARE_COMPLETION(wait);
        char sense[SCSI_SENSE_BUFFERSIZE];
        int err = 0;
  
-       rq->rq_disk = bd_disk;
        /*
         * we need an extra reference to the request, so we can look at
         * it after io completion
                rq->sense_len = 0;
        }
  
-       rq->flags |= REQ_NOMERGE;
        rq->waiting = &wait;
-       rq->end_io = blk_end_sync_rq;
-       elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
-       generic_unplug_device(q);
+       blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
        wait_for_completion(&wait);
        rq->waiting = NULL;
  
@@@ -2277,7 -2347,45 +2373,45 @@@ int blkdev_issue_flush(struct block_dev
  
  EXPORT_SYMBOL(blkdev_issue_flush);
  
 -void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
+ /**
+  * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
+  * @q:                device queue
+  * @disk:     gendisk
+  * @error_sector:     error offset
+  *
+  * Description:
+  *    Devices understanding the SCSI command set, can use this function as
+  *    a helper for issuing a cache flush. Note: driver is required to store
+  *    the error offset (in case of error flushing) in ->sector of struct
+  *    request.
+  */
+ int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+                              sector_t *error_sector)
+ {
+       struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
+       int ret;
+       rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+       rq->sector = 0;
+       memset(rq->cmd, 0, sizeof(rq->cmd));
+       rq->cmd[0] = 0x35;
+       rq->cmd_len = 12;
+       rq->data = NULL;
+       rq->data_len = 0;
+       rq->timeout = 60 * HZ;
+       ret = blk_execute_rq(q, disk, rq, 0);
+       if (ret && error_sector)
+               *error_sector = rq->sector;
+       blk_put_request(rq);
+       return ret;
+ }
+ EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
 +static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
  {
        int rw = rq_data_dir(rq);
  
@@@ -2359,6 -2467,7 +2493,6 @@@ static void __blk_put_request(request_q
                return;
  
        req->rq_status = RQ_INACTIVE;
 -      req->q = NULL;
        req->rl = NULL;
  
        /*
@@@ -2487,8 -2596,6 +2621,8 @@@ static int attempt_merge(request_queue_
                req->rq_disk->in_flight--;
        }
  
 +      req->ioprio = ioprio_best(req->ioprio, next->ioprio);
 +
        __blk_put_request(q, next);
        return 1;
  }
@@@ -2537,17 -2644,25 +2671,17 @@@ void blk_attempt_remerge(request_queue_
  
  EXPORT_SYMBOL(blk_attempt_remerge);
  
 -/*
 - * Non-locking blk_attempt_remerge variant.
 - */
 -void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
 -{
 -      attempt_back_merge(q, rq);
 -}
 -
 -EXPORT_SYMBOL(__blk_attempt_remerge);
 -
  static int __make_request(request_queue_t *q, struct bio *bio)
  {
 -      struct request *req, *freereq = NULL;
 +      struct request *req;
        int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
 +      unsigned short prio;
        sector_t sector;
  
        sector = bio->bi_sector;
        nr_sectors = bio_sectors(bio);
        cur_nr_sectors = bio_cur_sectors(bio);
 +      prio = bio_prio(bio);
  
        rw = bio_data_dir(bio);
        sync = bio_sync(bio);
        spin_lock_prefetch(q->queue_lock);
  
        barrier = bio_barrier(bio);
 -      if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) {
 +      if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
                err = -EOPNOTSUPP;
                goto end_io;
        }
  
 -again:
        spin_lock_irq(q->queue_lock);
  
 -      if (elv_queue_empty(q)) {
 -              blk_plug_device(q);
 -              goto get_rq;
 -      }
 -      if (barrier)
 +      if (unlikely(barrier) || elv_queue_empty(q))
                goto get_rq;
  
        el_ret = elv_merge(q, &req, bio);
                        req->biotail->bi_next = bio;
                        req->biotail = bio;
                        req->nr_sectors = req->hard_nr_sectors += nr_sectors;
 +                      req->ioprio = ioprio_best(req->ioprio, prio);
                        drive_stat_acct(req, nr_sectors, 0);
                        if (!attempt_back_merge(q, req))
                                elv_merged_request(q, req);
                        req->hard_cur_sectors = cur_nr_sectors;
                        req->sector = req->hard_sector = sector;
                        req->nr_sectors = req->hard_nr_sectors += nr_sectors;
 +                      req->ioprio = ioprio_best(req->ioprio, prio);
                        drive_stat_acct(req, nr_sectors, 0);
                        if (!attempt_front_merge(q, req))
                                elv_merged_request(q, req);
                        goto out;
  
 -              /*
 -               * elevator says don't/can't merge. get new request
 -               */
 -              case ELEVATOR_NO_MERGE:
 -                      break;
 -
 +              /* ELV_NO_MERGE: elevator says don't/can't merge. */
                default:
 -                      printk("elevator returned crap (%d)\n", el_ret);
 -                      BUG();
 +                      ;
        }
  
 +get_rq:
        /*
 -       * Grab a free request from the freelist - if that is empty, check
 -       * if we are doing read ahead and abort instead of blocking for
 -       * a free slot.
 +       * Grab a free request. This is might sleep but can not fail.
 +       * Returns with the queue unlocked.
 +       */
 +      req = get_request_wait(q, rw, bio);
 +
 +      /*
 +       * After dropping the lock and possibly sleeping here, our request
 +       * may now be mergeable after it had proven unmergeable (above).
 +       * We don't worry about that case for efficiency. It won't happen
 +       * often, and the elevators are able to handle it.
         */
 -get_rq:
 -      if (freereq) {
 -              req = freereq;
 -              freereq = NULL;
 -      } else {
 -              spin_unlock_irq(q->queue_lock);
 -              if ((freereq = get_request(q, rw, GFP_ATOMIC)) == NULL) {
 -                      /*
 -                       * READA bit set
 -                       */
 -                      err = -EWOULDBLOCK;
 -                      if (bio_rw_ahead(bio))
 -                              goto end_io;
 -      
 -                      freereq = get_request_wait(q, rw);
 -              }
 -              goto again;
 -      }
  
        req->flags |= REQ_CMD;
  
        /*
         * REQ_BARRIER implies no merging, but lets make it explicit
         */
 -      if (barrier)
 +      if (unlikely(barrier))
                req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
  
        req->errors = 0;
        req->buffer = bio_data(bio);    /* see ->buffer comment above */
        req->waiting = NULL;
        req->bio = req->biotail = bio;
 +      req->ioprio = prio;
        req->rq_disk = bio->bi_bdev->bd_disk;
        req->start_time = jiffies;
  
 +      spin_lock_irq(q->queue_lock);
 +      if (elv_queue_empty(q))
 +              blk_plug_device(q);
        add_request(q, req);
  out:
 -      if (freereq)
 -              __blk_put_request(q, freereq);
        if (sync)
                __generic_unplug_device(q);
  
@@@ -2686,7 -2818,7 +2820,7 @@@ static inline void blk_partition_remap(
        if (bdev != bdev->bd_contains) {
                struct hd_struct *p = bdev->bd_part;
  
 -              switch (bio->bi_rw) {
 +              switch (bio_data_dir(bio)) {
                case READ:
                        p->read_sectors += bio_sectors(bio);
                        p->reads++;
@@@ -2705,7 -2837,6 +2839,7 @@@ void blk_finish_queue_drain(request_que
  {
        struct request_list *rl = &q->rq;
        struct request *rq;
 +      int requeued = 0;
  
        spin_lock_irq(q->queue_lock);
        clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
                rq = list_entry_rq(q->drain_list.next);
  
                list_del_init(&rq->queuelist);
 -              __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
 +              elv_requeue_request(q, rq);
 +              requeued++;
        }
  
 +      if (requeued)
 +              q->request_fn(q);
 +
        spin_unlock_irq(q->queue_lock);
  
        wake_up(&rl->wait[0]);
@@@ -2775,7 -2902,7 +2909,7 @@@ static inline void block_wait_queue_run
  {
        DEFINE_WAIT(wait);
  
 -      while (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
 +      while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
                struct request_list *rl = &q->rq;
  
                prepare_to_wait_exclusive(&rl->drain, &wait,
@@@ -2884,7 -3011,7 +3018,7 @@@ end_io
                        goto end_io;
                }
  
 -              if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))
 +              if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
                        goto end_io;
  
                block_wait_queue_running(q);
@@@ -2917,7 -3044,7 +3051,7 @@@ void submit_bio(int rw, struct bio *bio
  
        BIO_BUG_ON(!bio->bi_size);
        BIO_BUG_ON(!bio->bi_io_vec);
 -      bio->bi_rw = rw;
 +      bio->bi_rw |= rw;
        if (rw & WRITE)
                mod_page_state(pgpgout, count);
        else
  
  EXPORT_SYMBOL(submit_bio);
  
 -void blk_recalc_rq_segments(struct request *rq)
 +static void blk_recalc_rq_segments(struct request *rq)
  {
        struct bio *bio, *prevbio = NULL;
        int nr_phys_segs, nr_hw_segs;
        rq->nr_hw_segments = nr_hw_segs;
  }
  
 -void blk_recalc_rq_sectors(struct request *rq, int nsect)
 +static void blk_recalc_rq_sectors(struct request *rq, int nsect)
  {
        if (blk_fs_request(rq)) {
                rq->hard_sector += nsect;
@@@ -3274,11 -3401,8 +3408,11 @@@ void exit_io_context(void
        struct io_context *ioc;
  
        local_irq_save(flags);
 +      task_lock(current);
        ioc = current->io_context;
        current->io_context = NULL;
 +      ioc->task = NULL;
 +      task_unlock(current);
        local_irq_restore(flags);
  
        if (ioc->aic && ioc->aic->exit)
  
  /*
   * If the current task has no IO context then create one and initialise it.
 - * If it does have a context, take a ref on it.
 + * Otherwise, return its existing IO context.
   *
 - * This is always called in the context of the task which submitted the I/O.
 - * But weird things happen, so we disable local interrupts to ensure exclusive
 - * access to *current.
 + * This returned IO context doesn't have a specifically elevated refcount,
 + * but since the current task itself holds a reference, the context can be
 + * used in general code, so long as it stays within `current` context.
   */
 -struct io_context *get_io_context(int gfp_flags)
 +struct io_context *current_io_context(int gfp_flags)
  {
        struct task_struct *tsk = current;
 -      unsigned long flags;
        struct io_context *ret;
  
 -      local_irq_save(flags);
        ret = tsk->io_context;
 -      if (ret)
 -              goto out;
 -
 -      local_irq_restore(flags);
 +      if (likely(ret))
 +              return ret;
  
        ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
        if (ret) {
                atomic_set(&ret->refcount, 1);
 -              ret->pid = tsk->pid;
 +              ret->task = current;
 +              ret->set_ioprio = NULL;
                ret->last_waited = jiffies; /* doesn't matter... */
                ret->nr_batch_requests = 0; /* because this is 0 */
                ret->aic = NULL;
                ret->cic = NULL;
 -              spin_lock_init(&ret->lock);
 -
 -              local_irq_save(flags);
 +              tsk->io_context = ret;
 +      }
  
 -              /*
 -               * very unlikely, someone raced with us in setting up the task
 -               * io context. free new context and just grab a reference.
 -               */
 -              if (!tsk->io_context)
 -                      tsk->io_context = ret;
 -              else {
 -                      kmem_cache_free(iocontext_cachep, ret);
 -                      ret = tsk->io_context;
 -              }
 +      return ret;
 +}
 +EXPORT_SYMBOL(current_io_context);
  
 -out:
 +/*
 + * If the current task has no IO context then create one and initialise it.
 + * If it does have a context, take a ref on it.
 + *
 + * This is always called in the context of the task which submitted the I/O.
 + */
 +struct io_context *get_io_context(int gfp_flags)
 +{
 +      struct io_context *ret;
 +      ret = current_io_context(gfp_flags);
 +      if (likely(ret))
                atomic_inc(&ret->refcount);
 -              local_irq_restore(flags);
 -      }
 -
        return ret;
  }
  EXPORT_SYMBOL(get_io_context);
@@@ -3542,7 -3670,7 +3676,7 @@@ queue_attr_show(struct kobject *kobj, s
  
        q = container_of(kobj, struct request_queue, kobj);
        if (!entry->show)
 -              return 0;
 +              return -EIO;
  
        return entry->show(q, page);
  }
@@@ -3556,7 -3684,7 +3690,7 @@@ queue_attr_store(struct kobject *kobj, 
  
        q = container_of(kobj, struct request_queue, kobj);
        if (!entry->store)
 -              return -EINVAL;
 +              return -EIO;
  
        return entry->store(q, page, length);
  }
@@@ -3566,7 -3694,7 +3700,7 @@@ static struct sysfs_ops queue_sysfs_op
        .store  = queue_attr_store,
  };
  
 -struct kobj_type queue_ktype = {
 +static struct kobj_type queue_ktype = {
        .sysfs_ops      = &queue_sysfs_ops,
        .default_attrs  = default_attrs,
  };
diff --combined drivers/ide/ide-disk.c
index c9d3a00a3c0c643bedcefd299d41d9075a08c036,9176da7a98585bbddd35fa4544959dd9690bfcf4..234f5de3e929b6c0d10ee46a994e200f16f62646
@@@ -119,10 -119,6 +119,10 @@@ static int lba_capacity_is_ok (struct h
  {
        unsigned long lba_sects, chs_sects, head, tail;
  
 +      /* No non-LBA info .. so valid! */
 +      if (id->cyls == 0)
 +              return 1;
 +
        /*
         * The ATA spec tells large drives to return
         * C/H/S = 16383/16/63 independent of their size.
@@@ -754,7 -750,7 +754,7 @@@ static int idedisk_issue_flush(request_
  
        idedisk_prepare_flush(q, rq);
  
-       ret = blk_execute_rq(q, disk, rq);
+       ret = blk_execute_rq(q, disk, rq, 0);
  
        /*
         * if we failed and caller wants error offset, get it
@@@ -1219,8 -1215,7 +1219,8 @@@ static int ide_disk_probe(struct devic
        if (!idkp)
                goto failed;
  
 -      g = alloc_disk(1 << PARTN_BITS);
 +      g = alloc_disk_node(1 << PARTN_BITS,
 +                      hwif_to_node(drive->hwif));
        if (!g)
                goto out_free_idkp;
  
diff --combined fs/bio.c
index 1f2d4649b188015076353340055a4ebdd1e0a6b1,24e4045788e2aed120056c40ac297ed264fd3272..e49cf7dd2e92ab4dc6deb8c13d20f161ede6d452
+++ b/fs/bio.c
@@@ -25,6 -25,7 +25,7 @@@
  #include <linux/module.h>
  #include <linux/mempool.h>
  #include <linux/workqueue.h>
+ #include <scsi/sg.h>          /* for struct sg_iovec */
  
  #define BIO_POOL_SIZE 256
  
@@@ -52,7 -53,7 +53,7 @@@ struct biovec_slab 
   */
  
  #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) }
 -static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] = {
 +static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
        BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES),
  };
  #undef BV
@@@ -248,16 -249,19 +249,16 @@@ inline void __bio_clone(struct bio *bio
  {
        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));
 +      memcpy(bio->bi_io_vec, bio_src->bi_io_vec,
 +              bio_src->bi_max_vecs * sizeof(struct bio_vec));
  
        bio->bi_sector = bio_src->bi_sector;
        bio->bi_bdev = bio_src->bi_bdev;
        bio->bi_flags |= 1 << BIO_CLONED;
        bio->bi_rw = bio_src->bi_rw;
 -
 -      /*
 -       * notes -- maybe just leave bi_idx alone. assume identical mapping
 -       * for the clone
 -       */
        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);
  }
@@@ -546,22 -550,34 +547,34 @@@ out_bmd
        return ERR_PTR(ret);
  }
  
- static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
-                                 unsigned long uaddr, unsigned int len,
-                                 int write_to_vm)
+ static struct bio *__bio_map_user_iov(request_queue_t *q,
+                                     struct block_device *bdev,
+                                     struct sg_iovec *iov, int iov_count,
+                                     int write_to_vm)
  {
-       unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       unsigned long start = uaddr >> PAGE_SHIFT;
-       const int nr_pages = end - start;
-       int ret, offset, i;
+       int i, j;
+       int nr_pages = 0;
        struct page **pages;
        struct bio *bio;
+       int cur_page = 0;
+       int ret, offset;
  
-       /*
-        * transfer and buffer must be aligned to at least hardsector
-        * size for now, in the future we can relax this restriction
-        */
-       if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+       for (i = 0; i < iov_count; i++) {
+               unsigned long uaddr = (unsigned long)iov[i].iov_base;
+               unsigned long len = iov[i].iov_len;
+               unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               unsigned long start = uaddr >> PAGE_SHIFT;
+               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
+                */
+               if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+                       return ERR_PTR(-EINVAL);
+       }
+       if (!nr_pages)
                return ERR_PTR(-EINVAL);
  
        bio = bio_alloc(GFP_KERNEL, nr_pages);
        if (!pages)
                goto out;
  
-       down_read(&current->mm->mmap_sem);
-       ret = get_user_pages(current, current->mm, uaddr, nr_pages,
-                                               write_to_vm, 0, pages, NULL);
-       up_read(&current->mm->mmap_sem);
-       if (ret < nr_pages)
-               goto out;
-       bio->bi_bdev = bdev;
-       offset = uaddr & ~PAGE_MASK;
-       for (i = 0; i < nr_pages; i++) {
-               unsigned int bytes = PAGE_SIZE - offset;
-               if (len <= 0)
-                       break;
-               if (bytes > len)
-                       bytes = len;
+       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;
+               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;
+               
+               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);
+               if (ret < local_nr_pages)
+                       goto out_unmap;
+               offset = uaddr & ~PAGE_MASK;
+               for (j = cur_page; j < page_limit; j++) {
+                       unsigned int bytes = PAGE_SIZE - offset;
+                       if (len <= 0)
+                               break;
+                       
+                       if (bytes > len)
+                               bytes = len;
+                       /*
+                        * sorry...
+                        */
+                       if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes)
+                               break;
+                       len -= bytes;
+                       offset = 0;
+               }
  
+               cur_page = j;
                /*
-                * sorry...
+                * release the pages we didn't map into the bio, if any
                 */
-               if (__bio_add_page(q, bio, pages[i], bytes, offset) < bytes)
-                       break;
-               len -= bytes;
-               offset = 0;
+               while (j < page_limit)
+                       page_cache_release(pages[j++]);
        }
  
-       /*
-        * release the pages we didn't map into the bio, if any
-        */
-       while (i < nr_pages)
-               page_cache_release(pages[i++]);
        kfree(pages);
  
        /*
        if (!write_to_vm)
                bio->bi_rw |= (1 << BIO_RW);
  
+       bio->bi_bdev = bdev;
        bio->bi_flags |= (1 << BIO_USER_MAPPED);
        return bio;
- out:
+  out_unmap:
+       for (i = 0; i < nr_pages; i++) {
+               if(!pages[i])
+                       break;
+               page_cache_release(pages[i]);
+       }
+  out:
        kfree(pages);
        bio_put(bio);
        return ERR_PTR(ret);
   */
  struct bio *bio_map_user(request_queue_t *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_len = len;
+       return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm);
+ }
+ /**
+  *    bio_map_user_iov - map user sg_iovec table into bio
+  *    @q: the request_queue_t 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
+  *
+  *    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 sg_iovec *iov, int iov_count,
+                            int write_to_vm)
  {
        struct bio *bio;
+       int len = 0, i;
  
-       bio = __bio_map_user(q, bdev, uaddr, len, write_to_vm);
+       bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
  
        if (IS_ERR(bio))
                return bio;
         */
        bio_get(bio);
  
+       for (i = 0; i < iov_count; i++)
+               len += iov[i].iov_len;
        if (bio->bi_size == len)
                return bio;
  
@@@ -698,6 -761,82 +758,82 @@@ 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)
+ {
+       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)
+ {
+       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;
+       int offset, i;
+       struct bio *bio;
+       bio = bio_alloc(gfp_mask, nr_pages);
+       if (!bio)
+               return ERR_PTR(-ENOMEM);
+       offset = offset_in_page(kaddr);
+       for (i = 0; i < nr_pages; i++) {
+               unsigned int bytes = PAGE_SIZE - offset;
+               if (len <= 0)
+                       break;
+               if (bytes > len)
+                       bytes = len;
+               if (__bio_add_page(q, bio, virt_to_page(data), bytes,
+                                  offset) < bytes)
+                       break;
+               data += bytes;
+               len -= bytes;
+               offset = 0;
+       }
+       bio->bi_end_io = bio_map_kern_endio;
+       return bio;
+ }
+ /**
+  *    bio_map_kern    -       map kernel address into bio
+  *    @q: the request_queue_t for the bio
+  *    @data: pointer to buffer to map
+  *    @len: length in bytes
+  *    @gfp_mask: allocation flags for bio allocation
+  *
+  *    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;
+       bio = __bio_map_kern(q, data, len, gfp_mask);
+       if (IS_ERR(bio))
+               return bio;
+       if (bio->bi_size == len)
+               return bio;
+       /*
+        * Don't support partial mappings.
+        */
+       bio_put(bio);
+       return ERR_PTR(-EINVAL);
+ }
  /*
   * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions
   * for performing direct-IO in BIOs.
@@@ -1085,6 -1224,7 +1221,7 @@@ EXPORT_SYMBOL(bio_add_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);
  EXPORT_SYMBOL(bio_split_pool);
diff --combined include/linux/bio.h
index 36ef29fa0d8b64a1cc2e2406bd9a8b30f83ab026,ebcd03ba2e200a4f77613288f0ad7c356d559971..4fda06da56c1c9fc5eeeb1f340cf3b00b2fdbe47
@@@ -22,7 -22,6 +22,7 @@@
  
  #include <linux/highmem.h>
  #include <linux/mempool.h>
 +#include <linux/ioprio.h>
  
  /* Platforms may set this to teach the BIO layer about IOMMU hardware. */
  #include <asm/io.h>
@@@ -150,19 -149,6 +150,19 @@@ struct bio 
  #define BIO_RW_FAILFAST       3
  #define BIO_RW_SYNC   4
  
 +/*
 + * upper 16 bits of bi_rw define the io priority of this bio
 + */
 +#define BIO_PRIO_SHIFT        (8 * sizeof(unsigned long) - IOPRIO_BITS)
 +#define bio_prio(bio) ((bio)->bi_rw >> BIO_PRIO_SHIFT)
 +#define bio_prio_valid(bio)   ioprio_valid(bio_prio(bio))
 +
 +#define bio_set_prio(bio, prio)               do {                    \
 +      WARN_ON(prio >= (1 << IOPRIO_BITS));                    \
 +      (bio)->bi_rw &= ((1UL << BIO_PRIO_SHIFT) - 1);          \
 +      (bio)->bi_rw |= ((unsigned long) (prio) << BIO_PRIO_SHIFT);     \
 +} while (0)
 +
  /*
   * various member access, note that bio_data should of course not be used
   * on highmem page vectors
@@@ -295,7 -281,13 +295,13 @@@ extern int bio_add_page(struct bio *, s
  extern int bio_get_nr_vecs(struct block_device *);
  extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
                                unsigned long, unsigned int, int);
+ struct sg_iovec;
+ extern struct bio *bio_map_user_iov(struct request_queue *,
+                                   struct block_device *,
+                                   struct sg_iovec *, int, int);
  extern void bio_unmap_user(struct bio *);
+ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
+                               unsigned int);
  extern void bio_set_pages_dirty(struct bio *bio);
  extern void bio_check_pages_dirty(struct bio *bio);
  extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
diff --combined include/linux/blkdev.h
index 19bd8e7e11bfcac95586ce28722730f7d4596118,a48dc12c6699addfa940f5f85fd3e34faaf3214b..aefa26fbae8add64ee373d9742523b534eaec7ce
@@@ -54,23 -54,16 +54,23 @@@ struct as_io_context 
  
  struct cfq_queue;
  struct cfq_io_context {
 -      void (*dtor)(struct cfq_io_context *);
 -      void (*exit)(struct cfq_io_context *);
 -
 -      struct io_context *ioc;
 -
        /*
         * circular list of cfq_io_contexts belonging to a process io context
         */
        struct list_head list;
        struct cfq_queue *cfqq;
 +      void *key;
 +
 +      struct io_context *ioc;
 +
 +      unsigned long last_end_request;
 +      unsigned long last_queue;
 +      unsigned long ttime_total;
 +      unsigned long ttime_samples;
 +      unsigned long ttime_mean;
 +
 +      void (*dtor)(struct cfq_io_context *);
 +      void (*exit)(struct cfq_io_context *);
  };
  
  /*
@@@ -80,9 -73,7 +80,9 @@@
   */
  struct io_context {
        atomic_t refcount;
 -      pid_t pid;
 +      struct task_struct *task;
 +
 +      int (*set_ioprio)(struct io_context *, unsigned int);
  
        /*
         * For request batching
        unsigned long last_waited; /* Time last woken after wait for request */
        int nr_batch_requests;     /* Number of requests left in the batch */
  
 -      spinlock_t lock;
 -
        struct as_io_context *aic;
        struct cfq_io_context *cic;
  };
  
  void put_io_context(struct io_context *ioc);
  void exit_io_context(void);
 +struct io_context *current_io_context(int gfp_flags);
  struct io_context *get_io_context(int gfp_flags);
  void copy_io_context(struct io_context **pdst, struct io_context **psrc);
  void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
@@@ -142,8 -134,6 +142,8 @@@ struct request 
  
        void *elevator_private;
  
 +      unsigned short ioprio;
 +
        int rq_status;  /* should split this into a few status bits */
        struct gendisk *rq_disk;
        int errors;
@@@ -295,6 -285,9 +295,6 @@@ enum blk_queue_state 
        Queue_up,
  };
  
 -#define BLK_TAGS_PER_LONG     (sizeof(unsigned long) * 8)
 -#define BLK_TAGS_MASK         (BLK_TAGS_PER_LONG - 1)
 -
  struct blk_queue_tag {
        struct request **tag_index;     /* map of busy tags */
        unsigned long *tag_map;         /* bit map of free/busy tags */
@@@ -403,7 -396,6 +403,7 @@@ struct request_queu
         */
        unsigned int            sg_timeout;
        unsigned int            sg_reserved_size;
 +      int                     node;
  
        struct list_head        drain_list;
  
@@@ -550,12 -542,15 +550,12 @@@ extern void generic_make_request(struc
  extern void blk_put_request(struct request *);
  extern void blk_end_sync_rq(struct request *rq);
  extern void blk_attempt_remerge(request_queue_t *, struct request *);
 -extern void __blk_attempt_remerge(request_queue_t *, struct request *);
  extern struct request *blk_get_request(request_queue_t *, int, int);
  extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
  extern void blk_requeue_request(request_queue_t *, struct request *);
  extern void blk_plug_device(request_queue_t *);
  extern int blk_remove_plug(request_queue_t *);
  extern void blk_recount_segments(request_queue_t *, struct bio *);
 -extern int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *);
 -extern int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *);
  extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
  extern void blk_start_queue(request_queue_t *q);
  extern void blk_stop_queue(request_queue_t *q);
@@@ -563,10 -558,12 +563,12 @@@ extern void blk_sync_queue(struct reque
  extern void __blk_stop_queue(request_queue_t *q);
  extern void blk_run_queue(request_queue_t *);
  extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
- extern struct request *blk_rq_map_user(request_queue_t *, int, void __user *, unsigned int);
- extern int blk_rq_unmap_user(struct request *, struct bio *, unsigned int);
- extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *);
+ extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
+ extern int blk_rq_unmap_user(struct bio *, unsigned int);
+ extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, unsigned int);
+ extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
+ extern int blk_execute_rq(request_queue_t *, struct gendisk *,
+                         struct request *, int);
  static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
  {
        return bdev->bd_disk->queue;
@@@ -620,8 -617,6 +622,8 @@@ static inline void blkdev_dequeue_reque
  /*
   * Access functions for manipulating queue properties
   */
 +extern request_queue_t *blk_init_queue_node(request_fn_proc *rfn,
 +                                      spinlock_t *lock, int node_id);
  extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *);
  extern void blk_cleanup_queue(request_queue_t *);
  extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
@@@ -639,6 -634,7 +641,6 @@@ extern void blk_queue_dma_alignment(req
  extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
  extern void blk_queue_ordered(request_queue_t *, int);
  extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
 -extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
  extern struct request *blk_start_pre_flush(request_queue_t *,struct request *);
  extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int);
  extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int);
@@@ -652,8 -648,7 +654,8 @@@ extern void blk_wait_queue_drained(requ
  extern void blk_finish_queue_drain(request_queue_t *);
  
  int blk_get_queue(request_queue_t *);
 -request_queue_t *blk_alloc_queue(int);
 +request_queue_t *blk_alloc_queue(int gfp_mask);
 +request_queue_t *blk_alloc_queue_node(int,int);
  #define blk_put_queue(q) blk_cleanup_queue((q))
  
  /*
@@@ -682,6 -677,8 +684,6 @@@ extern int blkdev_issue_flush(struct bl
  
  #define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
  
 -extern void drive_stat_acct(struct request *, int, int);
 -
  static inline int queue_hardsect_size(request_queue_t *q)
  {
        int retval = 512;