Merge branch 'for-2.6.25' of git://git.kernel.dk/linux-2.6-block
Linus Torvalds [Mon, 28 Jan 2008 21:51:56 +0000 (08:51 +1100)]
* 'for-2.6.25' of git://git.kernel.dk/linux-2.6-block:
  block: implement drain buffers
  __bio_clone: don't calculate hw/phys segment counts
  block: allow queue dma_alignment of zero
  blktrace: Add blktrace ioctls to SCSI generic devices

1  2 
block/ll_rw_blk.c
include/linux/blkdev.h

diff --combined block/ll_rw_blk.c
@@@ -347,6 -347,7 +347,6 @@@ unsigned blk_ordered_req_seq(struct req
  void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
  {
        struct request *rq;
 -      int uptodate;
  
        if (error && !q->orderr)
                q->orderr = error;
        /*
         * Okay, sequence complete.
         */
        q->ordseq = 0;
        rq = q->orig_bar_rq;
  
 -      end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
 -      end_that_request_last(rq, uptodate);
 +      if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq)))
 +              BUG();
  }
  
  static void pre_flush_end_io(struct request *rq, int error)
@@@ -481,9 -486,9 +481,9 @@@ int blk_do_ordered(struct request_queu
                         * ORDERED_NONE while this request is on it.
                         */
                        blkdev_dequeue_request(rq);
 -                      end_that_request_first(rq, -EOPNOTSUPP,
 -                                             rq->hard_nr_sectors);
 -                      end_that_request_last(rq, -EOPNOTSUPP);
 +                      if (__blk_end_request(rq, -EOPNOTSUPP,
 +                                            blk_rq_bytes(rq)))
 +                              BUG();
                        *rqp = NULL;
                        return 0;
                }
@@@ -721,6 -726,45 +721,45 @@@ void blk_queue_stack_limits(struct requ
  EXPORT_SYMBOL(blk_queue_stack_limits);
  
  /**
+  * blk_queue_dma_drain - Set up a drain buffer for excess dma.
+  *
+  * @q:  the request queue for the device
+  * @buf:      physically contiguous buffer
+  * @size:     size of the buffer in bytes
+  *
+  * Some devices have excess DMA problems and can't simply discard (or
+  * zero fill) the unwanted piece of the transfer.  They have to have a
+  * real area of memory to transfer it into.  The use case for this is
+  * ATAPI devices in DMA mode.  If the packet command causes a transfer
+  * bigger than the transfer size some HBAs will lock up if there
+  * aren't DMA elements to contain the excess transfer.  What this API
+  * does is adjust the queue so that the buf is always appended
+  * silently to the scatterlist.
+  *
+  * Note: This routine adjusts max_hw_segments to make room for
+  * appending the drain buffer.  If you call
+  * blk_queue_max_hw_segments() or blk_queue_max_phys_segments() after
+  * calling this routine, you must set the limit to one fewer than your
+  * device can support otherwise there won't be room for the drain
+  * buffer.
+  */
+ int blk_queue_dma_drain(struct request_queue *q, void *buf,
+                               unsigned int size)
+ {
+       if (q->max_hw_segments < 2 || q->max_phys_segments < 2)
+               return -EINVAL;
+       /* make room for appending the drain */
+       --q->max_hw_segments;
+       --q->max_phys_segments;
+       q->dma_drain_buffer = buf;
+       q->dma_drain_size = size;
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(blk_queue_dma_drain);
+ /**
   * blk_queue_segment_boundary - set boundary rules for segment merging
   * @q:  the request queue for the device
   * @mask:  the memory boundary mask
@@@ -1374,6 -1418,16 +1413,16 @@@ new_segment
                bvprv = bvec;
        } /* segments in rq */
  
+       if (q->dma_drain_size) {
+               sg->page_link &= ~0x02;
+               sg = sg_next(sg);
+               sg_set_page(sg, virt_to_page(q->dma_drain_buffer),
+                           q->dma_drain_size,
+                           ((unsigned long)q->dma_drain_buffer) &
+                           (PAGE_SIZE - 1));
+               nsegs++;
+       }
        if (sg)
                sg_mark_end(sg);
  
@@@ -3432,36 -3486,29 +3481,36 @@@ static void blk_recalc_rq_sectors(struc
        }
  }
  
 -static int __end_that_request_first(struct request *req, int uptodate,
 +/**
 + * __end_that_request_first - end I/O on a request
 + * @req:      the request being processed
 + * @error:    0 for success, < 0 for error
 + * @nr_bytes: number of bytes to complete
 + *
 + * Description:
 + *     Ends I/O on a number of bytes attached to @req, and sets it up
 + *     for the next range of segments (if any) in the cluster.
 + *
 + * Return:
 + *     0 - we are done with this request, call end_that_request_last()
 + *     1 - still buffers pending for this request
 + **/
 +static int __end_that_request_first(struct request *req, int error,
                                    int nr_bytes)
  {
 -      int total_bytes, bio_nbytes, error, next_idx = 0;
 +      int total_bytes, bio_nbytes, next_idx = 0;
        struct bio *bio;
  
        blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE);
  
        /*
 -       * extend uptodate bool to allow < 0 value to be direct io error
 -       */
 -      error = 0;
 -      if (end_io_error(uptodate))
 -              error = !uptodate ? -EIO : uptodate;
 -
 -      /*
         * for a REQ_BLOCK_PC request, we want to carry any eventual
         * sense key with us all the way through
         */
        if (!blk_pc_request(req))
                req->errors = 0;
  
 -      if (!uptodate) {
 +      if (error) {
                if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
                        printk("end_request: I/O error, dev %s, sector %llu\n",
                                req->rq_disk ? req->rq_disk->disk_name : "?",
        return 1;
  }
  
 -/**
 - * end_that_request_first - end I/O on a request
 - * @req:      the request being processed
 - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
 - * @nr_sectors: number of sectors to end I/O on
 - *
 - * Description:
 - *     Ends I/O on a number of sectors attached to @req, and sets it up
 - *     for the next range of segments (if any) in the cluster.
 - *
 - * Return:
 - *     0 - we are done with this request, call end_that_request_last()
 - *     1 - still buffers pending for this request
 - **/
 -int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
 -{
 -      return __end_that_request_first(req, uptodate, nr_sectors << 9);
 -}
 -
 -EXPORT_SYMBOL(end_that_request_first);
 -
 -/**
 - * end_that_request_chunk - end I/O on a request
 - * @req:      the request being processed
 - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
 - * @nr_bytes: number of bytes to complete
 - *
 - * Description:
 - *     Ends I/O on a number of bytes attached to @req, and sets it up
 - *     for the next range of segments (if any). Like end_that_request_first(),
 - *     but deals with bytes instead of sectors.
 - *
 - * Return:
 - *     0 - we are done with this request, call end_that_request_last()
 - *     1 - still buffers pending for this request
 - **/
 -int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
 -{
 -      return __end_that_request_first(req, uptodate, nr_bytes);
 -}
 -
 -EXPORT_SYMBOL(end_that_request_chunk);
 -
  /*
   * splice the completion data to a local structure and hand off to
   * process_completion_queue() to complete the requests
@@@ -3634,15 -3724,17 +3683,15 @@@ EXPORT_SYMBOL(blk_complete_request)
  /*
   * queue lock must be held
   */
 -void end_that_request_last(struct request *req, int uptodate)
 +static void end_that_request_last(struct request *req, int error)
  {
        struct gendisk *disk = req->rq_disk;
 -      int error;
  
 -      /*
 -       * extend uptodate bool to allow < 0 value to be direct io error
 -       */
 -      error = 0;
 -      if (end_io_error(uptodate))
 -              error = !uptodate ? -EIO : uptodate;
 +      if (blk_rq_tagged(req))
 +              blk_queue_end_tag(req->q, req);
 +
 +      if (blk_queued_rq(req))
 +              blkdev_dequeue_request(req);
  
        if (unlikely(laptop_mode) && blk_fs_request(req))
                laptop_io_completion();
                disk_round_stats(disk);
                disk->in_flight--;
        }
 +
        if (req->end_io)
                req->end_io(req, error);
 -      else
 +      else {
 +              if (blk_bidi_rq(req))
 +                      __blk_put_request(req->next_rq->q, req->next_rq);
 +
                __blk_put_request(req->q, req);
 +      }
  }
  
 -EXPORT_SYMBOL(end_that_request_last);
 -
  static inline void __end_request(struct request *rq, int uptodate,
 -                               unsigned int nr_bytes, int dequeue)
 +                               unsigned int nr_bytes)
  {
 -      if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
 -              if (dequeue)
 -                      blkdev_dequeue_request(rq);
 -              add_disk_randomness(rq->rq_disk);
 -              end_that_request_last(rq, uptodate);
 -      }
 +      int error = 0;
 +
 +      if (uptodate <= 0)
 +              error = uptodate ? uptodate : -EIO;
 +
 +      __blk_end_request(rq, error, nr_bytes);
  }
  
 -static unsigned int rq_byte_size(struct request *rq)
 +/**
 + * blk_rq_bytes - Returns bytes left to complete in the entire request
 + **/
 +unsigned int blk_rq_bytes(struct request *rq)
  {
        if (blk_fs_request(rq))
                return rq->hard_nr_sectors << 9;
  
        return rq->data_len;
  }
 +EXPORT_SYMBOL_GPL(blk_rq_bytes);
 +
 +/**
 + * blk_rq_cur_bytes - Returns bytes left to complete in the current segment
 + **/
 +unsigned int blk_rq_cur_bytes(struct request *rq)
 +{
 +      if (blk_fs_request(rq))
 +              return rq->current_nr_sectors << 9;
 +
 +      if (rq->bio)
 +              return rq->bio->bi_size;
 +
 +      return rq->data_len;
 +}
 +EXPORT_SYMBOL_GPL(blk_rq_cur_bytes);
  
  /**
   * end_queued_request - end all I/O on a queued request
   **/
  void end_queued_request(struct request *rq, int uptodate)
  {
 -      __end_request(rq, uptodate, rq_byte_size(rq), 1);
 +      __end_request(rq, uptodate, blk_rq_bytes(rq));
  }
  EXPORT_SYMBOL(end_queued_request);
  
   **/
  void end_dequeued_request(struct request *rq, int uptodate)
  {
 -      __end_request(rq, uptodate, rq_byte_size(rq), 0);
 +      __end_request(rq, uptodate, blk_rq_bytes(rq));
  }
  EXPORT_SYMBOL(end_dequeued_request);
  
   **/
  void end_request(struct request *req, int uptodate)
  {
 -      __end_request(req, uptodate, req->hard_cur_sectors << 9, 1);
 +      __end_request(req, uptodate, req->hard_cur_sectors << 9);
  }
  EXPORT_SYMBOL(end_request);
  
 +/**
 + * blk_end_io - Generic end_io function to complete a request.
 + * @rq:           the request being processed
 + * @error:        0 for success, < 0 for error
 + * @nr_bytes:     number of bytes to complete @rq
 + * @bidi_bytes:   number of bytes to complete @rq->next_rq
 + * @drv_callback: function called between completion of bios in the request
 + *                and completion of the request.
 + *                If the callback returns non 0, this helper returns without
 + *                completion of the request.
 + *
 + * Description:
 + *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
 + *     If @rq has leftover, sets it up for the next range of segments.
 + *
 + * Return:
 + *     0 - we are done with this request
 + *     1 - this request is not freed yet, it still has pending buffers.
 + **/
 +static int blk_end_io(struct request *rq, int error, int nr_bytes,
 +                    int bidi_bytes, int (drv_callback)(struct request *))
 +{
 +      struct request_queue *q = rq->q;
 +      unsigned long flags = 0UL;
 +
 +      if (blk_fs_request(rq) || blk_pc_request(rq)) {
 +              if (__end_that_request_first(rq, error, nr_bytes))
 +                      return 1;
 +
 +              /* Bidi request must be completed as a whole */
 +              if (blk_bidi_rq(rq) &&
 +                  __end_that_request_first(rq->next_rq, error, bidi_bytes))
 +                      return 1;
 +      }
 +
 +      /* Special feature for tricky drivers */
 +      if (drv_callback && drv_callback(rq))
 +              return 1;
 +
 +      add_disk_randomness(rq->rq_disk);
 +
 +      spin_lock_irqsave(q->queue_lock, flags);
 +      end_that_request_last(rq, error);
 +      spin_unlock_irqrestore(q->queue_lock, flags);
 +
 +      return 0;
 +}
 +
 +/**
 + * blk_end_request - Helper function for drivers to complete the request.
 + * @rq:       the request being processed
 + * @error:    0 for success, < 0 for error
 + * @nr_bytes: number of bytes to complete
 + *
 + * Description:
 + *     Ends I/O on a number of bytes attached to @rq.
 + *     If @rq has leftover, sets it up for the next range of segments.
 + *
 + * Return:
 + *     0 - we are done with this request
 + *     1 - still buffers pending for this request
 + **/
 +int blk_end_request(struct request *rq, int error, int nr_bytes)
 +{
 +      return blk_end_io(rq, error, nr_bytes, 0, NULL);
 +}
 +EXPORT_SYMBOL_GPL(blk_end_request);
 +
 +/**
 + * __blk_end_request - Helper function for drivers to complete the request.
 + * @rq:       the request being processed
 + * @error:    0 for success, < 0 for error
 + * @nr_bytes: number of bytes to complete
 + *
 + * Description:
 + *     Must be called with queue lock held unlike blk_end_request().
 + *
 + * Return:
 + *     0 - we are done with this request
 + *     1 - still buffers pending for this request
 + **/
 +int __blk_end_request(struct request *rq, int error, int nr_bytes)
 +{
 +      if (blk_fs_request(rq) || blk_pc_request(rq)) {
 +              if (__end_that_request_first(rq, error, nr_bytes))
 +                      return 1;
 +      }
 +
 +      add_disk_randomness(rq->rq_disk);
 +
 +      end_that_request_last(rq, error);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(__blk_end_request);
 +
 +/**
 + * blk_end_bidi_request - Helper function for drivers to complete bidi request.
 + * @rq:         the bidi request being processed
 + * @error:      0 for success, < 0 for error
 + * @nr_bytes:   number of bytes to complete @rq
 + * @bidi_bytes: number of bytes to complete @rq->next_rq
 + *
 + * Description:
 + *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
 + *
 + * Return:
 + *     0 - we are done with this request
 + *     1 - still buffers pending for this request
 + **/
 +int blk_end_bidi_request(struct request *rq, int error, int nr_bytes,
 +                       int bidi_bytes)
 +{
 +      return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
 +}
 +EXPORT_SYMBOL_GPL(blk_end_bidi_request);
 +
 +/**
 + * blk_end_request_callback - Special helper function for tricky drivers
 + * @rq:           the request being processed
 + * @error:        0 for success, < 0 for error
 + * @nr_bytes:     number of bytes to complete
 + * @drv_callback: function called between completion of bios in the request
 + *                and completion of the request.
 + *                If the callback returns non 0, this helper returns without
 + *                completion of the request.
 + *
 + * Description:
 + *     Ends I/O on a number of bytes attached to @rq.
 + *     If @rq has leftover, sets it up for the next range of segments.
 + *
 + *     This special helper function is used only for existing tricky drivers.
 + *     (e.g. cdrom_newpc_intr() of ide-cd)
 + *     This interface will be removed when such drivers are rewritten.
 + *     Don't use this interface in other places anymore.
 + *
 + * Return:
 + *     0 - we are done with this request
 + *     1 - this request is not freed yet.
 + *         this request still has pending buffers or
 + *         the driver doesn't want to finish this request yet.
 + **/
 +int blk_end_request_callback(struct request *rq, int error, int nr_bytes,
 +                           int (drv_callback)(struct request *))
 +{
 +      return blk_end_io(rq, error, nr_bytes, 0, drv_callback);
 +}
 +EXPORT_SYMBOL_GPL(blk_end_request_callback);
 +
  static void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
                            struct bio *bio)
  {
@@@ -3981,100 -3902,55 +4030,100 @@@ int __init blk_dev_init(void
        return 0;
  }
  
 +static void cfq_dtor(struct io_context *ioc)
 +{
 +      struct cfq_io_context *cic[1];
 +      int r;
 +
 +      /*
 +       * We don't have a specific key to lookup with, so use the gang
 +       * lookup to just retrieve the first item stored. The cfq exit
 +       * function will iterate the full tree, so any member will do.
 +       */
 +      r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1);
 +      if (r > 0)
 +              cic[0]->dtor(ioc);
 +}
 +
  /*
 - * IO Context helper functions
 + * IO Context helper functions. put_io_context() returns 1 if there are no
 + * more users of this io context, 0 otherwise.
   */
 -void put_io_context(struct io_context *ioc)
 +int put_io_context(struct io_context *ioc)
  {
        if (ioc == NULL)
 -              return;
 +              return 1;
  
        BUG_ON(atomic_read(&ioc->refcount) == 0);
  
        if (atomic_dec_and_test(&ioc->refcount)) {
                rcu_read_lock();
                if (ioc->aic && ioc->aic->dtor)
                        ioc->aic->dtor(ioc->aic);
 -              if (ioc->cic_root.rb_node != NULL) {
 -                      struct rb_node *n = rb_first(&ioc->cic_root);
 -
 -                      cic = rb_entry(n, struct cfq_io_context, rb_node);
 -                      cic->dtor(ioc);
 -              }
                rcu_read_unlock();
 +              cfq_dtor(ioc);
  
                kmem_cache_free(iocontext_cachep, ioc);
 +              return 1;
        }
 +      return 0;
  }
  EXPORT_SYMBOL(put_io_context);
  
 +static void cfq_exit(struct io_context *ioc)
 +{
 +      struct cfq_io_context *cic[1];
 +      int r;
 +
 +      rcu_read_lock();
 +      /*
 +       * See comment for cfq_dtor()
 +       */
 +      r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1);
 +      rcu_read_unlock();
 +
 +      if (r > 0)
 +              cic[0]->exit(ioc);
 +}
 +
  /* Called by the exitting task */
  void exit_io_context(void)
  {
        struct io_context *ioc;
 -      struct cfq_io_context *cic;
  
        task_lock(current);
        ioc = current->io_context;
        current->io_context = NULL;
        task_unlock(current);
  
 -      ioc->task = NULL;
 -      if (ioc->aic && ioc->aic->exit)
 -              ioc->aic->exit(ioc->aic);
 -      if (ioc->cic_root.rb_node != NULL) {
 -              cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
 -              cic->exit(ioc);
 +      if (atomic_dec_and_test(&ioc->nr_tasks)) {
 +              if (ioc->aic && ioc->aic->exit)
 +                      ioc->aic->exit(ioc->aic);
 +              cfq_exit(ioc);
 +
 +              put_io_context(ioc);
 +      }
 +}
 +
 +struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
 +{
 +      struct io_context *ret;
 +
 +      ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
 +      if (ret) {
 +              atomic_set(&ret->refcount, 1);
 +              atomic_set(&ret->nr_tasks, 1);
 +              spin_lock_init(&ret->lock);
 +              ret->ioprio_changed = 0;
 +              ret->ioprio = 0;
 +              ret->last_waited = jiffies; /* doesn't matter... */
 +              ret->nr_batch_requests = 0; /* because this is 0 */
 +              ret->aic = NULL;
 +              INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
 +              ret->ioc_data = NULL;
        }
  
 -      put_io_context(ioc);
 +      return ret;
  }
  
  /*
@@@ -4094,8 -3970,16 +4143,8 @@@ static struct io_context *current_io_co
        if (likely(ret))
                return ret;
  
 -      ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
 +      ret = alloc_io_context(gfp_flags, node);
        if (ret) {
 -              atomic_set(&ret->refcount, 1);
 -              ret->task = current;
 -              ret->ioprio_changed = 0;
 -              ret->last_waited = jiffies; /* doesn't matter... */
 -              ret->nr_batch_requests = 0; /* because this is 0 */
 -              ret->aic = NULL;
 -              ret->cic_root.rb_node = NULL;
 -              ret->ioc_data = NULL;
                /* make sure set_task_ioprio() sees the settings above */
                smp_wmb();
                tsk->io_context = ret;
   */
  struct io_context *get_io_context(gfp_t gfp_flags, int node)
  {
 -      struct io_context *ret;
 -      ret = current_io_context(gfp_flags, node);
 -      if (likely(ret))
 -              atomic_inc(&ret->refcount);
 +      struct io_context *ret = NULL;
 +
 +      /*
 +       * Check for unlikely race with exiting task. ioc ref count is
 +       * zero when ioc is being detached.
 +       */
 +      do {
 +              ret = current_io_context(gfp_flags, node);
 +              if (unlikely(!ret))
 +                      break;
 +      } while (!atomic_inc_not_zero(&ret->refcount));
 +
        return ret;
  }
  EXPORT_SYMBOL(get_io_context);
diff --combined include/linux/blkdev.h
@@@ -34,10 -34,83 +34,10 @@@ struct sg_io_hdr
  #define BLKDEV_MIN_RQ 4
  #define BLKDEV_MAX_RQ 128     /* Default maximum */
  
 -/*
 - * This is the per-process anticipatory I/O scheduler state.
 - */
 -struct as_io_context {
 -      spinlock_t lock;
 -
 -      void (*dtor)(struct as_io_context *aic); /* destructor */
 -      void (*exit)(struct as_io_context *aic); /* called on task exit */
 -
 -      unsigned long state;
 -      atomic_t nr_queued; /* queued reads & sync writes */
 -      atomic_t nr_dispatched; /* number of requests gone to the drivers */
 -
 -      /* IO History tracking */
 -      /* Thinktime */
 -      unsigned long last_end_request;
 -      unsigned long ttime_total;
 -      unsigned long ttime_samples;
 -      unsigned long ttime_mean;
 -      /* Layout pattern */
 -      unsigned int seek_samples;
 -      sector_t last_request_pos;
 -      u64 seek_total;
 -      sector_t seek_mean;
 -};
 -
 -struct cfq_queue;
 -struct cfq_io_context {
 -      struct rb_node rb_node;
 -      void *key;
 -
 -      struct cfq_queue *cfqq[2];
 -
 -      struct io_context *ioc;
 -
 -      unsigned long last_end_request;
 -      sector_t last_request_pos;
 -
 -      unsigned long ttime_total;
 -      unsigned long ttime_samples;
 -      unsigned long ttime_mean;
 -
 -      unsigned int seek_samples;
 -      u64 seek_total;
 -      sector_t seek_mean;
 -
 -      struct list_head queue_list;
 -
 -      void (*dtor)(struct io_context *); /* destructor */
 -      void (*exit)(struct io_context *); /* called on task exit */
 -};
 -
 -/*
 - * This is the per-process I/O subsystem state.  It is refcounted and
 - * kmalloc'ed. Currently all fields are modified in process io context
 - * (apart from the atomic refcount), so require no locking.
 - */
 -struct io_context {
 -      atomic_t refcount;
 -      struct task_struct *task;
 -
 -      unsigned int ioprio_changed;
 -
 -      /*
 -       * 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 */
 -
 -      struct as_io_context *aic;
 -      struct rb_root cic_root;
 -      void *ioc_data;
 -};
 -
 -void put_io_context(struct io_context *ioc);
 +int put_io_context(struct io_context *ioc);
  void exit_io_context(void);
  struct io_context *get_io_context(gfp_t gfp_flags, int node);
 +struct io_context *alloc_io_context(gfp_t gfp_flags, int node);
  void copy_io_context(struct io_context **pdst, struct io_context **psrc);
  void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
  
@@@ -356,6 -429,8 +356,8 @@@ struct request_queu
        unsigned int            max_segment_size;
  
        unsigned long           seg_boundary_mask;
+       void                    *dma_drain_buffer;
+       unsigned int            dma_drain_size;
        unsigned int            dma_alignment;
  
        struct blk_queue_tag    *queue_tags;
@@@ -464,8 -539,6 +466,8 @@@ enum 
  #define blk_fua_rq(rq)                ((rq)->cmd_flags & REQ_FUA)
  #define blk_bidi_rq(rq)               ((rq)->next_rq != NULL)
  #define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors)
 +/* rq->queuelist of dequeued request must be list_empty() */
 +#define blk_queued_rq(rq)     (!list_empty(&(rq)->queuelist))
  
  #define list_entry_rq(ptr)    list_entry((ptr), struct request, queuelist)
  
@@@ -645,32 -718,29 +647,32 @@@ static inline void blk_run_address_spac
  }
  
  /*
 - * end_request() and friends. Must be called with the request queue spinlock
 - * acquired. All functions called within end_request() _must_be_ atomic.
 + * blk_end_request() and friends.
 + * __blk_end_request() and end_request() must be called with
 + * the request queue spinlock acquired.
   *
   * Several drivers define their own end_request and call
 - * end_that_request_first() and end_that_request_last()
 - * for parts of the original function. This prevents
 - * code duplication in drivers.
 + * blk_end_request() for parts of the original function.
 + * This prevents code duplication in drivers.
   */
 -extern int end_that_request_first(struct request *, int, int);
 -extern int end_that_request_chunk(struct request *, int, int);
 -extern void end_that_request_last(struct request *, int);
 +extern int blk_end_request(struct request *rq, int error, int nr_bytes);
 +extern int __blk_end_request(struct request *rq, int error, int nr_bytes);
 +extern int blk_end_bidi_request(struct request *rq, int error, int nr_bytes,
 +                              int bidi_bytes);
  extern void end_request(struct request *, int);
  extern void end_queued_request(struct request *, int);
  extern void end_dequeued_request(struct request *, int);
 +extern int blk_end_request_callback(struct request *rq, int error, int nr_bytes,
 +                                  int (drv_callback)(struct request *));
  extern void blk_complete_request(struct request *);
  
  /*
 - * end_that_request_first/chunk() takes an uptodate argument. we account
 - * any value <= as an io error. 0 means -EIO for compatability reasons,
 - * any other < 0 value is the direct error type. An uptodate value of
 - * 1 indicates successful io completion
 + * blk_end_request() takes bytes instead of sectors as a complete size.
 + * blk_rq_bytes() returns bytes left to complete in the entire request.
 + * blk_rq_cur_bytes() returns bytes left to complete in the current segment.
   */
 -#define end_io_error(uptodate)        (unlikely((uptodate) <= 0))
 +extern unsigned int blk_rq_bytes(struct request *rq);
 +extern unsigned int blk_rq_cur_bytes(struct request *rq);
  
  static inline void blkdev_dequeue_request(struct request *req)
  {
@@@ -692,6 -762,8 +694,8 @@@ extern void blk_queue_max_hw_segments(s
  extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
  extern void blk_queue_hardsect_size(struct request_queue *, unsigned short);
  extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b);
+ extern int blk_queue_dma_drain(struct request_queue *q, void *buf,
+                              unsigned int size);
  extern void blk_queue_segment_boundary(struct request_queue *, unsigned long);
  extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn);
  extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *);
@@@ -768,12 -840,7 +772,7 @@@ static inline int bdev_hardsect_size(st
  
  static inline int queue_dma_alignment(struct request_queue *q)
  {
-       int retval = 511;
-       if (q && q->dma_alignment)
-               retval = q->dma_alignment;
-       return retval;
+       return q ? q->dma_alignment : 511;
  }
  
  /* assumes size > 256 */
@@@ -826,12 -893,6 +825,12 @@@ static inline void exit_io_context(void
  {
  }
  
 +static inline int put_io_context(struct io_context *ioc)
 +{
 +      return 1;
 +}
 +
 +
  #endif /* CONFIG_BLOCK */
  
  #endif