diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-18 16:21:18 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-18 16:21:18 -0400 |
| commit | 8a83f33100c691f5a576dba259cc05502dc358f0 (patch) | |
| tree | c10c74bd28026cefdb8caa1362a0ccc30ea695a5 | |
| parent | 5d5b1b9f79ebad81215d11e208e9bfa9679a4ddd (diff) | |
| parent | 24ecfbe27f65563909b14492afda2f1c21f7c044 (diff) | |
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
block: add blk_run_queue_async
block: blk_delay_queue() should use kblockd workqueue
md: fix up raid1/raid10 unplugging.
md: incorporate new plugging into raid5.
md: provide generic support for handling unplug callbacks.
md - remove old plugging code.
md/dm - remove remains of plug_fn callback.
md: use new plugging interface for RAID IO.
block: drop queue lock before calling __blk_run_queue() for kblockd punt
Revert "block: add callback function for unplug notification"
block: Enhance new plugging support to support general callbacks
| -rw-r--r-- | block/blk-core.c | 83 | ||||
| -rw-r--r-- | block/blk-exec.c | 2 | ||||
| -rw-r--r-- | block/blk-flush.c | 4 | ||||
| -rw-r--r-- | block/blk-settings.c | 16 | ||||
| -rw-r--r-- | block/blk.h | 1 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 6 | ||||
| -rw-r--r-- | block/elevator.c | 4 | ||||
| -rw-r--r-- | drivers/md/dm-raid.c | 8 | ||||
| -rw-r--r-- | drivers/md/md.c | 87 | ||||
| -rw-r--r-- | drivers/md/md.h | 26 | ||||
| -rw-r--r-- | drivers/md/raid1.c | 29 | ||||
| -rw-r--r-- | drivers/md/raid10.c | 27 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 61 | ||||
| -rw-r--r-- | drivers/md/raid5.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 2 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 12 | ||||
| -rw-r--r-- | include/linux/device-mapper.h | 1 |
18 files changed, 186 insertions, 187 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 78b7b0cb7216..5fa3dd2705c6 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -204,7 +204,7 @@ static void blk_delay_work(struct work_struct *work) | |||
| 204 | 204 | ||
| 205 | q = container_of(work, struct request_queue, delay_work.work); | 205 | q = container_of(work, struct request_queue, delay_work.work); |
| 206 | spin_lock_irq(q->queue_lock); | 206 | spin_lock_irq(q->queue_lock); |
| 207 | __blk_run_queue(q, false); | 207 | __blk_run_queue(q); |
| 208 | spin_unlock_irq(q->queue_lock); | 208 | spin_unlock_irq(q->queue_lock); |
| 209 | } | 209 | } |
| 210 | 210 | ||
| @@ -220,7 +220,8 @@ static void blk_delay_work(struct work_struct *work) | |||
| 220 | */ | 220 | */ |
| 221 | void blk_delay_queue(struct request_queue *q, unsigned long msecs) | 221 | void blk_delay_queue(struct request_queue *q, unsigned long msecs) |
| 222 | { | 222 | { |
| 223 | schedule_delayed_work(&q->delay_work, msecs_to_jiffies(msecs)); | 223 | queue_delayed_work(kblockd_workqueue, &q->delay_work, |
| 224 | msecs_to_jiffies(msecs)); | ||
| 224 | } | 225 | } |
| 225 | EXPORT_SYMBOL(blk_delay_queue); | 226 | EXPORT_SYMBOL(blk_delay_queue); |
| 226 | 227 | ||
| @@ -238,7 +239,7 @@ void blk_start_queue(struct request_queue *q) | |||
| 238 | WARN_ON(!irqs_disabled()); | 239 | WARN_ON(!irqs_disabled()); |
| 239 | 240 | ||
| 240 | queue_flag_clear(QUEUE_FLAG_STOPPED, q); | 241 | queue_flag_clear(QUEUE_FLAG_STOPPED, q); |
| 241 | __blk_run_queue(q, false); | 242 | __blk_run_queue(q); |
| 242 | } | 243 | } |
| 243 | EXPORT_SYMBOL(blk_start_queue); | 244 | EXPORT_SYMBOL(blk_start_queue); |
| 244 | 245 | ||
| @@ -296,9 +297,8 @@ EXPORT_SYMBOL(blk_sync_queue); | |||
| 296 | * Description: | 297 | * Description: |
| 297 | * See @blk_run_queue. This variant must be called with the queue lock | 298 | * See @blk_run_queue. This variant must be called with the queue lock |
| 298 | * held and interrupts disabled. | 299 | * held and interrupts disabled. |
| 299 | * | ||
| 300 | */ | 300 | */ |
| 301 | void __blk_run_queue(struct request_queue *q, bool force_kblockd) | 301 | void __blk_run_queue(struct request_queue *q) |
| 302 | { | 302 | { |
| 303 | if (unlikely(blk_queue_stopped(q))) | 303 | if (unlikely(blk_queue_stopped(q))) |
| 304 | return; | 304 | return; |
| @@ -307,7 +307,7 @@ void __blk_run_queue(struct request_queue *q, bool force_kblockd) | |||
| 307 | * Only recurse once to avoid overrunning the stack, let the unplug | 307 | * Only recurse once to avoid overrunning the stack, let the unplug |
| 308 | * handling reinvoke the handler shortly if we already got there. | 308 | * handling reinvoke the handler shortly if we already got there. |
| 309 | */ | 309 | */ |
| 310 | if (!force_kblockd && !queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { | 310 | if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { |
| 311 | q->request_fn(q); | 311 | q->request_fn(q); |
| 312 | queue_flag_clear(QUEUE_FLAG_REENTER, q); | 312 | queue_flag_clear(QUEUE_FLAG_REENTER, q); |
| 313 | } else | 313 | } else |
| @@ -316,6 +316,20 @@ void __blk_run_queue(struct request_queue *q, bool force_kblockd) | |||
| 316 | EXPORT_SYMBOL(__blk_run_queue); | 316 | EXPORT_SYMBOL(__blk_run_queue); |
| 317 | 317 | ||
| 318 | /** | 318 | /** |
| 319 | * blk_run_queue_async - run a single device queue in workqueue context | ||
| 320 | * @q: The queue to run | ||
| 321 | * | ||
| 322 | * Description: | ||
| 323 | * Tells kblockd to perform the equivalent of @blk_run_queue on behalf | ||
| 324 | * of us. | ||
| 325 | */ | ||
| 326 | void blk_run_queue_async(struct request_queue *q) | ||
| 327 | { | ||
| 328 | if (likely(!blk_queue_stopped(q))) | ||
| 329 | queue_delayed_work(kblockd_workqueue, &q->delay_work, 0); | ||
| 330 | } | ||
| 331 | |||
| 332 | /** | ||
| 319 | * blk_run_queue - run a single device queue | 333 | * blk_run_queue - run a single device queue |
| 320 | * @q: The queue to run | 334 | * @q: The queue to run |
| 321 | * | 335 | * |
| @@ -328,7 +342,7 @@ void blk_run_queue(struct request_queue *q) | |||
| 328 | unsigned long flags; | 342 | unsigned long flags; |
| 329 | 343 | ||
| 330 | spin_lock_irqsave(q->queue_lock, flags); | 344 | spin_lock_irqsave(q->queue_lock, flags); |
| 331 | __blk_run_queue(q, false); | 345 | __blk_run_queue(q); |
| 332 | spin_unlock_irqrestore(q->queue_lock, flags); | 346 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 333 | } | 347 | } |
| 334 | EXPORT_SYMBOL(blk_run_queue); | 348 | EXPORT_SYMBOL(blk_run_queue); |
| @@ -977,7 +991,7 @@ void blk_insert_request(struct request_queue *q, struct request *rq, | |||
| 977 | blk_queue_end_tag(q, rq); | 991 | blk_queue_end_tag(q, rq); |
| 978 | 992 | ||
| 979 | add_acct_request(q, rq, where); | 993 | add_acct_request(q, rq, where); |
| 980 | __blk_run_queue(q, false); | 994 | __blk_run_queue(q); |
| 981 | spin_unlock_irqrestore(q->queue_lock, flags); | 995 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 982 | } | 996 | } |
| 983 | EXPORT_SYMBOL(blk_insert_request); | 997 | EXPORT_SYMBOL(blk_insert_request); |
| @@ -1321,7 +1335,7 @@ get_rq: | |||
| 1321 | } else { | 1335 | } else { |
| 1322 | spin_lock_irq(q->queue_lock); | 1336 | spin_lock_irq(q->queue_lock); |
| 1323 | add_acct_request(q, req, where); | 1337 | add_acct_request(q, req, where); |
| 1324 | __blk_run_queue(q, false); | 1338 | __blk_run_queue(q); |
| 1325 | out_unlock: | 1339 | out_unlock: |
| 1326 | spin_unlock_irq(q->queue_lock); | 1340 | spin_unlock_irq(q->queue_lock); |
| 1327 | } | 1341 | } |
| @@ -2638,6 +2652,7 @@ void blk_start_plug(struct blk_plug *plug) | |||
| 2638 | 2652 | ||
| 2639 | plug->magic = PLUG_MAGIC; | 2653 | plug->magic = PLUG_MAGIC; |
| 2640 | INIT_LIST_HEAD(&plug->list); | 2654 | INIT_LIST_HEAD(&plug->list); |
| 2655 | INIT_LIST_HEAD(&plug->cb_list); | ||
| 2641 | plug->should_sort = 0; | 2656 | plug->should_sort = 0; |
| 2642 | 2657 | ||
| 2643 | /* | 2658 | /* |
| @@ -2670,12 +2685,41 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
| 2670 | */ | 2685 | */ |
| 2671 | static void queue_unplugged(struct request_queue *q, unsigned int depth, | 2686 | static void queue_unplugged(struct request_queue *q, unsigned int depth, |
| 2672 | bool from_schedule) | 2687 | bool from_schedule) |
| 2688 | __releases(q->queue_lock) | ||
| 2673 | { | 2689 | { |
| 2674 | trace_block_unplug(q, depth, !from_schedule); | 2690 | trace_block_unplug(q, depth, !from_schedule); |
| 2675 | __blk_run_queue(q, from_schedule); | ||
| 2676 | 2691 | ||
| 2677 | if (q->unplugged_fn) | 2692 | /* |
| 2678 | q->unplugged_fn(q); | 2693 | * If we are punting this to kblockd, then we can safely drop |
| 2694 | * the queue_lock before waking kblockd (which needs to take | ||
| 2695 | * this lock). | ||
| 2696 | */ | ||
| 2697 | if (from_schedule) { | ||
| 2698 | spin_unlock(q->queue_lock); | ||
| 2699 | blk_run_queue_async(q); | ||
| 2700 | } else { | ||
| 2701 | __blk_run_queue(q); | ||
| 2702 | spin_unlock(q->queue_lock); | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | } | ||
| 2706 | |||
| 2707 | static void flush_plug_callbacks(struct blk_plug *plug) | ||
| 2708 | { | ||
| 2709 | LIST_HEAD(callbacks); | ||
| 2710 | |||
| 2711 | if (list_empty(&plug->cb_list)) | ||
| 2712 | return; | ||
| 2713 | |||
| 2714 | list_splice_init(&plug->cb_list, &callbacks); | ||
| 2715 | |||
| 2716 | while (!list_empty(&callbacks)) { | ||
| 2717 | struct blk_plug_cb *cb = list_first_entry(&callbacks, | ||
| 2718 | struct blk_plug_cb, | ||
| 2719 | list); | ||
| 2720 | list_del(&cb->list); | ||
| 2721 | cb->callback(cb); | ||
| 2722 | } | ||
| 2679 | } | 2723 | } |
| 2680 | |||
