Merge branch 'blk-softirq' of git://brick.kernel.dk/data/git/linux-2.6-block
authorLinus Torvalds <torvalds@g5.osdl.org>
Mon, 9 Jan 2006 17:26:40 +0000 (09:26 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 9 Jan 2006 17:26:40 +0000 (09:26 -0800)
Manual merge for trivial #include changes

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

diff --combined block/ll_rw_blk.c
index c44d6fe9f6ceb4b542a22a016107c756e3160dfc,8e136450abc21bffc6c5844319f3d1eb6ce9c656..8e27d0ab0d7ccefef5a53d42c52978200040ca18
@@@ -26,6 -26,9 +26,8 @@@
  #include <linux/slab.h>
  #include <linux/swap.h>
  #include <linux/writeback.h>
 -#include <linux/blkdev.h>
+ #include <linux/interrupt.h>
+ #include <linux/cpu.h>
  
  /*
   * for max sense size
@@@ -61,13 -64,15 +63,15 @@@ static wait_queue_head_t congestion_wqh
  /*
   * Controlling structure to kblockd
   */
- static struct workqueue_struct *kblockd_workqueue; 
+ static struct workqueue_struct *kblockd_workqueue;
  
  unsigned long blk_max_low_pfn, blk_max_pfn;
  
  EXPORT_SYMBOL(blk_max_low_pfn);
  EXPORT_SYMBOL(blk_max_pfn);
  
+ static DEFINE_PER_CPU(struct list_head, blk_cpu_done);
  /* Amount of time in which a process may batch requests */
  #define BLK_BATCH_TIME        (HZ/50UL)
  
@@@ -206,6 -211,13 +210,13 @@@ void blk_queue_merge_bvec(request_queue
  
  EXPORT_SYMBOL(blk_queue_merge_bvec);
  
+ void blk_queue_softirq_done(request_queue_t *q, softirq_done_fn *fn)
+ {
+       q->softirq_done_fn = fn;
+ }
+ EXPORT_SYMBOL(blk_queue_softirq_done);
  /**
   * blk_queue_make_request - define an alternate make_request function for a device
   * @q:  the request queue for the device to be affected
@@@ -269,6 -281,7 +280,7 @@@ EXPORT_SYMBOL(blk_queue_make_request)
  static inline void rq_init(request_queue_t *q, struct request *rq)
  {
        INIT_LIST_HEAD(&rq->queuelist);
+       INIT_LIST_HEAD(&rq->donelist);
  
        rq->errors = 0;
        rq->rq_status = RQ_ACTIVE;
        rq->sense = NULL;
        rq->end_io = NULL;
        rq->end_io_data = NULL;
+       rq->completion_data = NULL;
  }
  
  /**
@@@ -2734,6 -2748,30 +2747,6 @@@ static inline int attempt_front_merge(r
        return 0;
  }
  
 -/**
 - * blk_attempt_remerge  - attempt to remerge active head with next request
 - * @q:    The &request_queue_t belonging to the device
 - * @rq:   The head request (usually)
 - *
 - * Description:
 - *    For head-active devices, the queue can easily be unplugged so quickly
 - *    that proper merging is not done on the front request. This may hurt
 - *    performance greatly for some devices. The block layer cannot safely
 - *    do merging on that first request for these queues, but the driver can
 - *    call this function and make it happen any way. Only the driver knows
 - *    when it is safe to do so.
 - **/
 -void blk_attempt_remerge(request_queue_t *q, struct request *rq)
 -{
 -      unsigned long flags;
 -
 -      spin_lock_irqsave(q->queue_lock, flags);
 -      attempt_back_merge(q, rq);
 -      spin_unlock_irqrestore(q->queue_lock, flags);
 -}
 -
 -EXPORT_SYMBOL(blk_attempt_remerge);
 -
  static void init_request_from_bio(struct request *req, struct bio *bio)
  {
        req->flags |= REQ_CMD;
@@@ -3261,6 -3299,87 +3274,87 @@@ int end_that_request_chunk(struct reque
  
  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
+  */
+ static void blk_done_softirq(struct softirq_action *h)
+ {
+       struct list_head *cpu_list;
+       LIST_HEAD(local_list);
+       local_irq_disable();
+       cpu_list = &__get_cpu_var(blk_cpu_done);
+       list_splice_init(cpu_list, &local_list);
+       local_irq_enable();
+       while (!list_empty(&local_list)) {
+               struct request *rq = list_entry(local_list.next, struct request, donelist);
+               list_del_init(&rq->donelist);
+               rq->q->softirq_done_fn(rq);
+       }
+ }
+ #ifdef CONFIG_HOTPLUG_CPU
+ static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
+                         void *hcpu)
+ {
+       /*
+        * If a CPU goes away, splice its entries to the current CPU
+        * and trigger a run of the softirq
+        */
+       if (action == CPU_DEAD) {
+               int cpu = (unsigned long) hcpu;
+               local_irq_disable();
+               list_splice_init(&per_cpu(blk_cpu_done, cpu),
+                                &__get_cpu_var(blk_cpu_done));
+               raise_softirq_irqoff(BLOCK_SOFTIRQ);
+               local_irq_enable();
+       }
+       return NOTIFY_OK;
+ }
+ static struct notifier_block __devinitdata blk_cpu_notifier = {
+       .notifier_call  = blk_cpu_notify,
+ };
+ #endif /* CONFIG_HOTPLUG_CPU */
+ /**
+  * blk_complete_request - end I/O on a request
+  * @req:      the request being processed
+  *
+  * Description:
+  *     Ends all I/O on a request. It does not handle partial completions,
+  *     unless the driver actually implements this in its completionc callback
+  *     through requeueing. Theh actual completion happens out-of-order,
+  *     through a softirq handler. The user must have registered a completion
+  *     callback through blk_queue_softirq_done().
+  **/
+ void blk_complete_request(struct request *req)
+ {
+       struct list_head *cpu_list;
+       unsigned long flags;
+       BUG_ON(!req->q->softirq_done_fn);
+               
+       local_irq_save(flags);
+       cpu_list = &__get_cpu_var(blk_cpu_done);
+       list_add_tail(&req->donelist, cpu_list);
+       raise_softirq_irqoff(BLOCK_SOFTIRQ);
+       local_irq_restore(flags);
+ }
+ EXPORT_SYMBOL(blk_complete_request);
+       
  /*
   * queue lock must be held
   */
@@@ -3339,6 -3458,8 +3433,8 @@@ EXPORT_SYMBOL(kblockd_flush)
  
  int __init blk_dev_init(void)
  {
+       int i;
        kblockd_workqueue = create_workqueue("kblockd");
        if (!kblockd_workqueue)
                panic("Failed to create kblockd\n");
        iocontext_cachep = kmem_cache_create("blkdev_ioc",
                        sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL);
  
+       for (i = 0; i < NR_CPUS; i++)
+               INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
+       open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
+ #ifdef CONFIG_HOTPLUG_CPU
+       register_cpu_notifier(&blk_cpu_notifier);
+ #endif
        blk_max_low_pfn = max_low_pfn;
        blk_max_pfn = max_pfn;
  
diff --combined include/linux/blkdev.h
index 96b2339916853d2ca95dae609b0a29e2592f5612,804cc4ec953328107018ab0eb70384b7f8d32b0f..02a585faa62cfd689510b943717cc6f79101184b
@@@ -118,9 -118,9 +118,9 @@@ struct request_list 
   * try to put the fields that are referenced together in the same cacheline
   */
  struct request {
-       struct list_head queuelist; /* looking for ->queue? you must _not_
-                                    * access it directly, use
-                                    * blkdev_dequeue_request! */
+       struct list_head queuelist;
+       struct list_head donelist;
        unsigned long flags;            /* see REQ_ bits below */
  
        /* Maintain bio traversal state for part by part I/O submission.
        struct bio *biotail;
  
        void *elevator_private;
+       void *completion_data;
  
        unsigned short ioprio;
  
@@@ -291,6 -292,7 +292,7 @@@ typedef int (merge_bvec_fn) (request_qu
  typedef void (activity_fn) (void *data, int rw);
  typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
  typedef void (prepare_flush_fn) (request_queue_t *, struct request *);
+ typedef void (softirq_done_fn)(struct request *);
  
  enum blk_queue_state {
        Queue_down,
@@@ -332,6 -334,7 +334,7 @@@ struct request_queu
        activity_fn             *activity_fn;
        issue_flush_fn          *issue_flush_fn;
        prepare_flush_fn        *prepare_flush_fn;
+       softirq_done_fn         *softirq_done_fn;
  
        /*
         * Dispatch queue sorting
@@@ -592,6 -595,7 +595,6 @@@ extern void generic_make_request(struc
  extern void blk_put_request(struct request *);
  extern void __blk_put_request(request_queue_t *, struct request *);
  extern void blk_end_sync_rq(struct request *rq, int error);
 -extern void blk_attempt_remerge(request_queue_t *, struct request *);
  extern struct request *blk_get_request(request_queue_t *, int, gfp_t);
  extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
  extern void blk_requeue_request(request_queue_t *, struct request *);
@@@ -645,6 -649,17 +648,17 @@@ extern int end_that_request_first(struc
  extern int end_that_request_chunk(struct request *, int, int);
  extern void end_that_request_last(struct request *, int);
  extern void end_request(struct request *req, int uptodate);
+ extern void blk_complete_request(struct request *);
+ static inline int rq_all_done(struct request *rq, unsigned int nr_bytes)
+ {
+       if (blk_fs_request(rq))
+               return (nr_bytes >= (rq->hard_nr_sectors << 9));
+       else if (blk_pc_request(rq))
+               return nr_bytes >= rq->data_len;
+       return 0;
+ }
  
  /*
   * end_that_request_first/chunk() takes an uptodate argument. we account
@@@ -693,6 -708,7 +707,7 @@@ extern void blk_queue_segment_boundary(
  extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn);
  extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);
  extern void blk_queue_dma_alignment(request_queue_t *, int);
+ extern void blk_queue_softirq_done(request_queue_t *, softirq_done_fn *);
  extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
  extern int blk_queue_ordered(request_queue_t *, unsigned, prepare_flush_fn *);
  extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
This page took 0.033183 seconds and 5 git commands to generate.