diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2009-04-06 08:48:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 11:04:53 -0400 |
commit | 1faa16d22877f4839bd433547d770c676d1d964c (patch) | |
tree | 9a0d50be1ef0358c1f53d7107413100904e7d526 /block | |
parent | 0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff) |
block: change the request allocation/congestion logic to be sync/async based
This makes sure that we never wait on async IO for sync requests, instead
of doing the split on writes vs reads.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 70 | ||||
-rw-r--r-- | block/blk-sysfs.c | 40 | ||||
-rw-r--r-- | block/elevator.c | 2 |
3 files changed, 56 insertions, 56 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 996ed906d8ca..a32b571aaaa2 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -484,11 +484,11 @@ static int blk_init_free_list(struct request_queue *q) | |||
484 | { | 484 | { |
485 | struct request_list *rl = &q->rq; | 485 | struct request_list *rl = &q->rq; |
486 | 486 | ||
487 | rl->count[READ] = rl->count[WRITE] = 0; | 487 | rl->count[BLK_RW_SYNC] = rl->count[BLK_RW_ASYNC] = 0; |
488 | rl->starved[READ] = rl->starved[WRITE] = 0; | 488 | rl->starved[BLK_RW_SYNC] = rl->starved[BLK_RW_ASYNC] = 0; |
489 | rl->elvpriv = 0; | 489 | rl->elvpriv = 0; |
490 | init_waitqueue_head(&rl->wait[READ]); | 490 | init_waitqueue_head(&rl->wait[BLK_RW_SYNC]); |
491 | init_waitqueue_head(&rl->wait[WRITE]); | 491 | init_waitqueue_head(&rl->wait[BLK_RW_ASYNC]); |
492 | 492 | ||
493 | rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, | 493 | rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, |
494 | mempool_free_slab, request_cachep, q->node); | 494 | mempool_free_slab, request_cachep, q->node); |
@@ -699,18 +699,18 @@ static void ioc_set_batching(struct request_queue *q, struct io_context *ioc) | |||
699 | ioc->last_waited = jiffies; | 699 | ioc->last_waited = jiffies; |
700 | } | 700 | } |
701 | 701 | ||
702 | static void __freed_request(struct request_queue *q, int rw) | 702 | static void __freed_request(struct request_queue *q, int sync) |
703 | { | 703 | { |
704 | struct request_list *rl = &q->rq; | 704 | struct request_list *rl = &q->rq; |
705 | 705 | ||
706 | if (rl->count[rw] < queue_congestion_off_threshold(q)) | 706 | if (rl->count[sync] < queue_congestion_off_threshold(q)) |
707 | blk_clear_queue_congested(q, rw); | 707 | blk_clear_queue_congested(q, sync); |
708 | 708 | ||
709 | if (rl->count[rw] + 1 <= q->nr_requests) { | 709 | if (rl->count[sync] + 1 <= q->nr_requests) { |
710 | if (waitqueue_active(&rl->wait[rw])) | 710 | if (waitqueue_active(&rl->wait[sync])) |
711 | wake_up(&rl->wait[rw]); | 711 | wake_up(&rl->wait[sync]); |
712 | 712 | ||
713 | blk_clear_queue_full(q, rw); | 713 | blk_clear_queue_full(q, sync); |
714 | } | 714 | } |
715 | } | 715 | } |
716 | 716 | ||
@@ -718,18 +718,18 @@ static void __freed_request(struct request_queue *q, int rw) | |||
718 | * A request has just been released. Account for it, update the full and | 718 | * A request has just been released. Account for it, update the full and |
719 | * congestion status, wake up any waiters. Called under q->queue_lock. | 719 | * congestion status, wake up any waiters. Called under q->queue_lock. |
720 | */ | 720 | */ |
721 | static void freed_request(struct request_queue *q, int rw, int priv) | 721 | static void freed_request(struct request_queue *q, int sync, int priv) |
722 | { | 722 | { |
723 | struct request_list *rl = &q->rq; | 723 | struct request_list *rl = &q->rq; |
724 | 724 | ||
725 | rl->count[rw]--; | 725 | rl->count[sync]--; |
726 | if (priv) | 726 | if (priv) |
727 | rl->elvpriv--; | 727 | rl->elvpriv--; |
728 | 728 | ||
729 | __freed_request(q, rw); | 729 | __freed_request(q, sync); |
730 | 730 | ||
731 | if (unlikely(rl->starved[rw ^ 1])) | 731 | if (unlikely(rl->starved[sync ^ 1])) |
732 | __freed_request(q, rw ^ 1); | 732 | __freed_request(q, sync ^ 1); |
733 | } | 733 | } |
734 | 734 | ||
735 | /* | 735 | /* |
@@ -743,15 +743,15 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
743 | struct request *rq = NULL; | 743 | struct request *rq = NULL; |
744 | struct request_list *rl = &q->rq; | 744 | struct request_list *rl = &q->rq; |
745 | struct io_context *ioc = NULL; | 745 | struct io_context *ioc = NULL; |
746 | const int rw = rw_flags & 0x01; | 746 | const bool is_sync = rw_is_sync(rw_flags) != 0; |
747 | int may_queue, priv; | 747 | int may_queue, priv; |
748 | 748 | ||
749 | may_queue = elv_may_queue(q, rw_flags); | 749 | may_queue = elv_may_queue(q, rw_flags); |
750 | if (may_queue == ELV_MQUEUE_NO) | 750 | if (may_queue == ELV_MQUEUE_NO) |
751 | goto rq_starved; | 751 | goto rq_starved; |
752 | 752 | ||
753 | if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) { | 753 | if (rl->count[is_sync]+1 >= queue_congestion_on_threshold(q)) { |
754 | if (rl->count[rw]+1 >= q->nr_requests) { | 754 | if (rl->count[is_sync]+1 >= q->nr_requests) { |
755 | ioc = current_io_context(GFP_ATOMIC, q->node); | 755 | ioc = current_io_context(GFP_ATOMIC, q->node); |
756 | /* | 756 | /* |
757 | * The queue will fill after this allocation, so set | 757 | * The queue will fill after this allocation, so set |
@@ -759,9 +759,9 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
759 | * This process will be allowed to complete a batch of | 759 | * This process will be allowed to complete a batch of |
760 | * requests, others will be blocked. | 760 | * requests, others will be blocked. |
761 | */ | 761 | */ |
762 | if (!blk_queue_full(q, rw)) { | 762 | if (!blk_queue_full(q, is_sync)) { |
763 | ioc_set_batching(q, ioc); | 763 | ioc_set_batching(q, ioc); |
764 | blk_set_queue_full(q, rw); | 764 | blk_set_queue_full(q, is_sync); |
765 | } else { | 765 | } else { |
766 | if (may_queue != ELV_MQUEUE_MUST | 766 | if (may_queue != ELV_MQUEUE_MUST |
767 | && !ioc_batching(q, ioc)) { | 767 | && !ioc_batching(q, ioc)) { |
@@ -774,7 +774,7 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
774 | } | 774 | } |
775 | } | 775 | } |
776 | } | 776 | } |
777 | blk_set_queue_congested(q, rw); | 777 | blk_set_queue_congested(q, is_sync); |
778 | } | 778 | } |
779 | 779 | ||
780 | /* | 780 | /* |
@@ -782,11 +782,11 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
782 | * limit of requests, otherwise we could have thousands of requests | 782 | * limit of requests, otherwise we could have thousands of requests |
783 | * allocated with any setting of ->nr_requests | 783 | * allocated with any setting of ->nr_requests |
784 | */ | 784 | */ |
785 | if (rl->count[rw] >= (3 * q->nr_requests / 2)) | 785 | if (rl->count[is_sync] >= (3 * q->nr_requests / 2)) |
786 | goto out; | 786 | goto out; |
787 | 787 | ||
788 | rl->count[rw]++; | 788 | rl->count[is_sync]++; |
789 | rl->starved[rw] = 0; | 789 | rl->starved[is_sync] = 0; |
790 | 790 | ||
791 | priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); | 791 | priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); |
792 | if (priv) | 792 | if (priv) |
@@ -804,7 +804,7 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
804 | * wait queue, but this is pretty rare. | 804 | * wait queue, but this is pretty rare. |
805 | */ | 805 | */ |
806 | spin_lock_irq(q->queue_lock); | 806 | spin_lock_irq(q->queue_lock); |
807 | freed_request(q, rw, priv); | 807 | freed_request(q, is_sync, priv); |
808 | 808 | ||
809 | /* | 809 | /* |
810 | * in the very unlikely event that allocation failed and no | 810 | * in the very unlikely event that allocation failed and no |
@@ -814,8 +814,8 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
814 | * rq mempool into READ and WRITE | 814 | * rq mempool into READ and WRITE |
815 | */ | 815 | */ |
816 | rq_starved: | 816 | rq_starved: |
817 | if (unlikely(rl->count[rw] == 0)) | 817 | if (unlikely(rl->count[is_sync] == 0)) |
818 | rl->starved[rw] = 1; | 818 | rl->starved[is_sync] = 1; |
819 | 819 | ||
820 | goto out; | 820 | goto out; |
821 | } | 821 | } |
@@ -829,7 +829,7 @@ rq_starved: | |||
829 | if (ioc_batching(q, ioc)) | 829 | if (ioc_batching(q, ioc)) |
830 | ioc->nr_batch_requests--; | 830 | ioc->nr_batch_requests--; |
831 | 831 | ||
832 | trace_block_getrq(q, bio, rw); | 832 | trace_block_getrq(q, bio, rw_flags & 1); |
833 | out: | 833 | out: |
834 | return rq; | 834 | return rq; |
835 | } | 835 | } |
@@ -843,7 +843,7 @@ out: | |||
843 | static struct request *get_request_wait(struct request_queue *q, int rw_flags, | 843 | static struct request *get_request_wait(struct request_queue *q, int rw_flags, |
844 | struct bio *bio) | 844 | struct bio *bio) |
845 | { | 845 | { |
846 | const int rw = rw_flags & 0x01; | 846 | const bool is_sync = rw_is_sync(rw_flags) != 0; |
847 | struct request *rq; | 847 | struct request *rq; |
848 | 848 | ||
849 | rq = get_request(q, rw_flags, bio, GFP_NOIO); | 849 | rq = get_request(q, rw_flags, bio, GFP_NOIO); |
@@ -852,10 +852,10 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags, | |||
852 | struct io_context *ioc; | 852 | struct io_context *ioc; |
853 | struct request_list *rl = &q->rq; | 853 | struct request_list *rl = &q->rq; |
854 | 854 | ||
855 | prepare_to_wait_exclusive(&rl->wait[rw], &wait, | 855 | prepare_to_wait_exclusive(&rl->wait[is_sync], &wait, |
856 | TASK_UNINTERRUPTIBLE); | 856 | TASK_UNINTERRUPTIBLE); |
857 | 857 | ||
858 | trace_block_sleeprq(q, bio, rw); | 858 | trace_block_sleeprq(q, bio, rw_flags & 1); |
859 | 859 | ||
860 | __generic_unplug_device(q); | 860 | __generic_unplug_device(q); |
861 | spin_unlock_irq(q->queue_lock); | 861 | spin_unlock_irq(q->queue_lock); |
@@ -871,7 +871,7 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags, | |||
871 | ioc_set_batching(q, ioc); | 871 | ioc_set_batching(q, ioc); |
872 | 872 | ||
873 | spin_lock_irq(q->queue_lock); | 873 | spin_lock_irq(q->queue_lock); |
874 | finish_wait(&rl->wait[rw], &wait); | 874 | finish_wait(&rl->wait[is_sync], &wait); |
875 | 875 | ||
876 | rq = get_request(q, rw_flags, bio, GFP_NOIO); | 876 | rq = get_request(q, rw_flags, bio, GFP_NOIO); |
877 | }; | 877 | }; |
@@ -1070,14 +1070,14 @@ void __blk_put_request(struct request_queue *q, struct request *req) | |||
1070 | * it didn't come out of our reserved rq pools | 1070 | * it didn't come out of our reserved rq pools |
1071 | */ | 1071 | */ |
1072 | if (req->cmd_flags & REQ_ALLOCED) { | 1072 | if (req->cmd_flags & REQ_ALLOCED) { |
1073 | int rw = rq_data_dir(req); | 1073 | int is_sync = rq_is_sync(req) != 0; |
1074 | int priv = req->cmd_flags & REQ_ELVPRIV; | 1074 | int priv = req->cmd_flags & REQ_ELVPRIV; |
1075 | 1075 | ||
1076 | BUG_ON(!list_empty(&req->queuelist)); | 1076 | BUG_ON(!list_empty(&req->queuelist)); |
1077 | BUG_ON(!hlist_unhashed(&req->hash)); | 1077 | BUG_ON(!hlist_unhashed(&req->hash)); |
1078 | 1078 | ||
1079 | blk_free_request(q, req); | 1079 | blk_free_request(q, req); |
1080 | freed_request(q, rw, priv); | 1080 | freed_request(q, is_sync, priv); |
1081 | } | 1081 | } |
1082 | } | 1082 | } |
1083 | EXPORT_SYMBOL_GPL(__blk_put_request); | 1083 | EXPORT_SYMBOL_GPL(__blk_put_request); |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index e29ddfc73cf4..3ff9bba3379a 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -48,28 +48,28 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count) | |||
48 | q->nr_requests = nr; | 48 | q->nr_requests = nr; |
49 | blk_queue_congestion_threshold(q); | 49 | blk_queue_congestion_threshold(q); |
50 | 50 | ||
51 | if (rl->count[READ] >= queue_congestion_on_threshold(q)) | 51 | if (rl->count[BLK_RW_SYNC] >= queue_congestion_on_threshold(q)) |
52 | blk_set_queue_congested(q, READ); | 52 | blk_set_queue_congested(q, BLK_RW_SYNC); |
53 | else if (rl->count[READ] < queue_congestion_off_threshold(q)) | 53 | else if (rl->count[BLK_RW_SYNC] < queue_congestion_off_threshold(q)) |
54 | blk_clear_queue_congested(q, READ); | 54 | blk_clear_queue_congested(q, BLK_RW_SYNC); |
55 | 55 | ||
56 | if (rl->count[WRITE] >= queue_congestion_on_threshold(q)) | 56 | if (rl->count[BLK_RW_ASYNC] >= queue_congestion_on_threshold(q)) |
57 | blk_set_queue_congested(q, WRITE); | 57 | blk_set_queue_congested(q, BLK_RW_ASYNC); |
58 | else if (rl->count[WRITE] < queue_congestion_off_threshold(q)) | 58 | else if (rl->count[BLK_RW_ASYNC] < queue_congestion_off_threshold(q)) |
59 | blk_clear_queue_congested(q, WRITE); | 59 | blk_clear_queue_congested(q, BLK_RW_ASYNC); |
60 | 60 | ||
61 | if (rl->count[READ] >= q->nr_requests) { | 61 | if (rl->count[BLK_RW_SYNC] >= q->nr_requests) { |
62 | blk_set_queue_full(q, READ); | 62 | blk_set_queue_full(q, BLK_RW_SYNC); |
63 | } else if (rl->count[READ]+1 <= q->nr_requests) { | 63 | } else if (rl->count[BLK_RW_SYNC]+1 <= q->nr_requests) { |
64 | blk_clear_queue_full(q, READ); | 64 | blk_clear_queue_full(q, BLK_RW_SYNC); |
65 | wake_up(&rl->wait[READ]); | 65 | wake_up(&rl->wait[BLK_RW_SYNC]); |
66 | } | 66 | } |
67 | 67 | ||
68 | if (rl->count[WRITE] >= q->nr_requests) { | 68 | if (rl->count[BLK_RW_ASYNC] >= q->nr_requests) { |
69 | blk_set_queue_full(q, WRITE); | 69 | blk_set_queue_full(q, BLK_RW_ASYNC); |
70 | } else if (rl->count[WRITE]+1 <= q->nr_requests) { | 70 | } else if (rl->count[BLK_RW_ASYNC]+1 <= q->nr_requests) { |
71 | blk_clear_queue_full(q, WRITE); | 71 | blk_clear_queue_full(q, BLK_RW_ASYNC); |
72 | wake_up(&rl->wait[WRITE]); | 72 | wake_up(&rl->wait[BLK_RW_ASYNC]); |
73 | } | 73 | } |
74 | spin_unlock_irq(q->queue_lock); | 74 | spin_unlock_irq(q->queue_lock); |
75 | return ret; | 75 | return ret; |
diff --git a/block/elevator.c b/block/elevator.c index 98259eda0ef6..ca6788a0195a 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -677,7 +677,7 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) | |||
677 | } | 677 | } |
678 | 678 | ||
679 | if (unplug_it && blk_queue_plugged(q)) { | 679 | if (unplug_it && blk_queue_plugged(q)) { |
680 | int nrq = q->rq.count[READ] + q->rq.count[WRITE] | 680 | int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC] |
681 | - q->in_flight; | 681 | - q->in_flight; |
682 | 682 | ||
683 | if (nrq >= q->unplug_thresh) | 683 | if (nrq >= q->unplug_thresh) |