Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / block / ll_rw_blk.c
index e5041a0..eee03a3 100644 (file)
@@ -638,7 +638,7 @@ void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr)
        /* Assume anything <= 4GB can be handled by IOMMU.
           Actually some IOMMUs can handle everything, but I don't
           know of a way to test this here. */
-       if (bounce_pfn < (0xffffffff>>PAGE_SHIFT))
+       if (bounce_pfn < (min_t(u64,0xffffffff,BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
                dma = 1;
        q->bounce_pfn = max_low_pfn;
 #else
@@ -1663,6 +1663,8 @@ static void blk_unplug_timeout(unsigned long data)
  **/
 void blk_start_queue(request_queue_t *q)
 {
+       WARN_ON(!irqs_disabled());
+
        clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
 
        /*
@@ -1732,8 +1734,21 @@ void blk_run_queue(struct request_queue *q)
 
        spin_lock_irqsave(q->queue_lock, flags);
        blk_remove_plug(q);
-       if (!elv_queue_empty(q))
-               q->request_fn(q);
+
+       /*
+        * Only recurse once to avoid overrunning the stack, let the unplug
+        * handling reinvoke the handler shortly if we already got there.
+        */
+       if (!elv_queue_empty(q)) {
+               if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+                       q->request_fn(q);
+                       clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
+               } else {
+                       blk_plug_device(q);
+                       kblockd_schedule_work(&q->unplug_work);
+               }
+       }
+
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);
@@ -1865,7 +1880,8 @@ EXPORT_SYMBOL(blk_alloc_queue_node);
  *    get dealt with eventually.
  *
  *    The queue spin lock must be held while manipulating the requests on the
- *    request queue.
+ *    request queue; this lock will be taken also from interrupt context, so irq
+ *    disabling is needed for it.
  *
  *    Function returns a pointer to the initialized request queue, or NULL if
  *    it didn't succeed.
@@ -2729,7 +2745,7 @@ static int attempt_merge(request_queue_t *q, struct request *req,
                return 0;
 
        /*
-        * not contigious
+        * not contiguous
         */
        if (req->sector + req->nr_sectors != next->sector)
                return 0;
@@ -2811,6 +2827,9 @@ static void init_request_from_bio(struct request *req, struct bio *bio)
        if (unlikely(bio_barrier(bio)))
                req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
 
+       if (bio_sync(bio))
+               req->flags |= REQ_RW_SYNC;
+
        req->errors = 0;
        req->hard_sector = req->sector = bio->bi_sector;
        req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio);
@@ -3346,12 +3365,11 @@ EXPORT_SYMBOL(end_that_request_chunk);
  */
 static void blk_done_softirq(struct softirq_action *h)
 {
-       struct list_head *cpu_list;
-       LIST_HEAD(local_list);
+       struct list_head *cpu_list, local_list;
 
        local_irq_disable();
        cpu_list = &__get_cpu_var(blk_cpu_done);
-       list_splice_init(cpu_list, &local_list);
+       list_replace_init(cpu_list, &local_list);
        local_irq_enable();
 
        while (!list_empty(&local_list)) {
@@ -3385,7 +3403,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
 }
 
 
-static struct notifier_block blk_cpu_notifier = {
+static struct notifier_block __devinitdata blk_cpu_notifier = {
        .notifier_call  = blk_cpu_notify,
 };
 
@@ -3397,7 +3415,7 @@ static struct notifier_block blk_cpu_notifier = {
  *
  * Description:
  *     Ends all I/O on a request. It does not handle partial completions,
- *     unless the driver actually implements this in its completionc callback
+ *     unless the driver actually implements this in its completion 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().
@@ -3439,7 +3457,12 @@ void end_that_request_last(struct request *req, int uptodate)
        if (unlikely(laptop_mode) && blk_fs_request(req))
                laptop_io_completion();
 
-       if (disk && blk_fs_request(req)) {
+       /*
+        * Account IO completion.  bar_rq isn't accounted as a normal
+        * IO on queueing nor completion.  Accounting the containing
+        * request is enough.
+        */
+       if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
                unsigned long duration = jiffies - req->start_time;
                const int rw = rq_data_dir(req);
 
@@ -3518,9 +3541,7 @@ int __init blk_dev_init(void)
                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
+       register_hotcpu_notifier(&blk_cpu_notifier);
 
        blk_max_low_pfn = max_low_pfn;
        blk_max_pfn = max_pfn;