diff options
Diffstat (limited to 'block/cfq-iosched.c')
| -rw-r--r-- | block/cfq-iosched.c | 151 |
1 files changed, 60 insertions, 91 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 74fae2daf87e..c8dbe38c81c8 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -239,7 +239,6 @@ enum cfqq_state_flags { | |||
| 239 | CFQ_CFQQ_FLAG_fifo_expire, | 239 | CFQ_CFQQ_FLAG_fifo_expire, |
| 240 | CFQ_CFQQ_FLAG_idle_window, | 240 | CFQ_CFQQ_FLAG_idle_window, |
| 241 | CFQ_CFQQ_FLAG_prio_changed, | 241 | CFQ_CFQQ_FLAG_prio_changed, |
| 242 | CFQ_CFQQ_FLAG_expired, | ||
| 243 | }; | 242 | }; |
| 244 | 243 | ||
| 245 | #define CFQ_CFQQ_FNS(name) \ | 244 | #define CFQ_CFQQ_FNS(name) \ |
| @@ -264,7 +263,6 @@ CFQ_CFQQ_FNS(must_dispatch); | |||
| 264 | CFQ_CFQQ_FNS(fifo_expire); | 263 | CFQ_CFQQ_FNS(fifo_expire); |
| 265 | CFQ_CFQQ_FNS(idle_window); | 264 | CFQ_CFQQ_FNS(idle_window); |
| 266 | CFQ_CFQQ_FNS(prio_changed); | 265 | CFQ_CFQQ_FNS(prio_changed); |
| 267 | CFQ_CFQQ_FNS(expired); | ||
| 268 | #undef CFQ_CFQQ_FNS | 266 | #undef CFQ_CFQQ_FNS |
| 269 | 267 | ||
| 270 | enum cfq_rq_state_flags { | 268 | enum cfq_rq_state_flags { |
| @@ -336,7 +334,7 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) | |||
| 336 | */ | 334 | */ |
| 337 | static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) | 335 | static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) |
| 338 | { | 336 | { |
| 339 | if (!cfqd->rq_in_driver && cfqd->busy_queues) | 337 | if (cfqd->busy_queues) |
| 340 | kblockd_schedule_work(&cfqd->unplug_work); | 338 | kblockd_schedule_work(&cfqd->unplug_work); |
| 341 | } | 339 | } |
| 342 | 340 | ||
| @@ -736,13 +734,63 @@ __cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 736 | cfqq->slice_left = 0; | 734 | cfqq->slice_left = 0; |
| 737 | cfq_clear_cfqq_must_alloc_slice(cfqq); | 735 | cfq_clear_cfqq_must_alloc_slice(cfqq); |
| 738 | cfq_clear_cfqq_fifo_expire(cfqq); | 736 | cfq_clear_cfqq_fifo_expire(cfqq); |
| 739 | cfq_clear_cfqq_expired(cfqq); | ||
| 740 | } | 737 | } |
| 741 | 738 | ||
| 742 | cfqd->active_queue = cfqq; | 739 | cfqd->active_queue = cfqq; |
| 743 | } | 740 | } |
| 744 | 741 | ||
| 745 | /* | 742 | /* |
| 743 | * current cfqq expired its slice (or was too idle), select new one | ||
| 744 | */ | ||
| 745 | static void | ||
| 746 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
| 747 | int preempted) | ||
| 748 | { | ||
| 749 | unsigned long now = jiffies; | ||
| 750 | |||
| 751 | if (cfq_cfqq_wait_request(cfqq)) | ||
| 752 | del_timer(&cfqd->idle_slice_timer); | ||
| 753 | |||
| 754 | if (!preempted && !cfq_cfqq_dispatched(cfqq)) { | ||
| 755 | cfqq->service_last = now; | ||
| 756 | cfq_schedule_dispatch(cfqd); | ||
| 757 | } | ||
| 758 | |||
| 759 | cfq_clear_cfqq_must_dispatch(cfqq); | ||
| 760 | cfq_clear_cfqq_wait_request(cfqq); | ||
| 761 | |||
| 762 | /* | ||
| 763 | * store what was left of this slice, if the queue idled out | ||
| 764 | * or was preempted | ||
| 765 | */ | ||
| 766 | if (time_after(cfqq->slice_end, now)) | ||
| 767 | cfqq->slice_left = cfqq->slice_end - now; | ||
| 768 | else | ||
| 769 | cfqq->slice_left = 0; | ||
| 770 | |||
| 771 | if (cfq_cfqq_on_rr(cfqq)) | ||
| 772 | cfq_resort_rr_list(cfqq, preempted); | ||
| 773 | |||
| 774 | if (cfqq == cfqd->active_queue) | ||
| 775 | cfqd->active_queue = NULL; | ||
| 776 | |||
| 777 | if (cfqd->active_cic) { | ||
| 778 | put_io_context(cfqd->active_cic->ioc); | ||
| 779 | cfqd->active_cic = NULL; | ||
| 780 | } | ||
| 781 | |||
| 782 | cfqd->dispatch_slice = 0; | ||
| 783 | } | ||
| 784 | |||
| 785 | static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted) | ||
| 786 | { | ||
| 787 | struct cfq_queue *cfqq = cfqd->active_queue; | ||
| 788 | |||
| 789 | if (cfqq) | ||
| 790 | __cfq_slice_expired(cfqd, cfqq, preempted); | ||
| 791 | } | ||
| 792 | |||
| 793 | /* | ||
| 746 | * 0 | 794 | * 0 |
| 747 | * 0,1 | 795 | * 0,1 |
| 748 | * 0,1,2 | 796 | * 0,1,2 |
| @@ -801,16 +849,7 @@ static int cfq_get_next_prio_level(struct cfq_data *cfqd) | |||
| 801 | 849 | ||
| 802 | static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | 850 | static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) |
| 803 | { | 851 | { |
| 804 | struct cfq_queue *cfqq; | 852 | struct cfq_queue *cfqq = NULL; |
| 805 | |||
| 806 | /* | ||
| 807 | * if current queue is expired but not done with its requests yet, | ||
| 808 | * wait for that to happen | ||
| 809 | */ | ||
| 810 | if ((cfqq = cfqd->active_queue) != NULL) { | ||
| 811 | if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq)) | ||
| 812 | return NULL; | ||
| 813 | } | ||
| 814 | 853 | ||
| 815 | /* | 854 | /* |
| 816 | * if current list is non-empty, grab first entry. if it is empty, | 855 | * if current list is non-empty, grab first entry. if it is empty, |
| @@ -837,66 +876,11 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | |||
| 837 | return cfqq; | 876 | return cfqq; |
| 838 | } | 877 | } |
| 839 | 878 | ||
| 840 | /* | ||
| 841 | * current cfqq expired its slice (or was too idle), select new one | ||
| 842 | */ | ||
| 843 | static void | ||
| 844 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
| 845 | int preempted) | ||
| 846 | { | ||
| 847 | unsigned long now = jiffies; | ||
| 848 | |||
| 849 | if (cfq_cfqq_wait_request(cfqq)) | ||
| 850 | del_timer(&cfqd->idle_slice_timer); | ||
| 851 | |||
| 852 | if (!preempted && !cfq_cfqq_dispatched(cfqq)) | ||
| 853 | cfqq->service_last = now; | ||
| 854 | |||
| 855 | cfq_clear_cfqq_must_dispatch(cfqq); | ||
| 856 | cfq_clear_cfqq_wait_request(cfqq); | ||
| 857 | |||
| 858 | /* | ||
| 859 | * store what was left of this slice, if the queue idled out | ||
| 860 | * or was preempted | ||
| 861 | */ | ||
| 862 | if (time_after(cfqq->slice_end, now)) | ||
| 863 | cfqq->slice_left = cfqq->slice_end - now; | ||
| 864 | else | ||
| 865 | cfqq->slice_left = 0; | ||
| 866 | |||
| 867 | if (cfq_cfqq_on_rr(cfqq)) | ||
| 868 | cfq_resort_rr_list(cfqq, preempted); | ||
| 869 | |||
| 870 | if (cfqq == cfqd->active_queue) | ||
| 871 | cfqd->active_queue = NULL; | ||
| 872 | |||
| 873 | if (cfqd->active_cic) { | ||
| 874 | put_io_context(cfqd->active_cic->ioc); | ||
| 875 | cfqd->active_cic = NULL; | ||
| 876 | } | ||
| 877 | |||
| 878 | cfqd->dispatch_slice = 0; | ||
| 879 | } | ||
| 880 | |||
| 881 | static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted) | ||
| 882 | { | ||
| 883 | struct cfq_queue *cfqq = cfqd->active_queue; | ||
| 884 | |||
| 885 | if (cfqq) { | ||
| 886 | /* | ||
| 887 | * use deferred expiry, if there are requests in progress as | ||
| 888 | * not to disturb the slice of the next queue | ||
| 889 | */ | ||
| 890 | if (cfq_cfqq_dispatched(cfqq)) | ||
| 891 | cfq_mark_cfqq_expired(cfqq); | ||
| 892 | else | ||
| 893 | __cfq_slice_expired(cfqd, cfqq, preempted); | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 879 | static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
| 898 | 880 | ||
| 899 | { | 881 | { |
| 882 | unsigned long sl; | ||
| 883 | |||
| 900 | WARN_ON(!RB_EMPTY(&cfqq->sort_list)); | 884 | WARN_ON(!RB_EMPTY(&cfqq->sort_list)); |
| 901 | WARN_ON(cfqq != cfqd->active_queue); | 885 | WARN_ON(cfqq != cfqd->active_queue); |
| 902 | 886 | ||
| @@ -916,13 +900,8 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 916 | cfq_mark_cfqq_must_dispatch(cfqq); | 900 | cfq_mark_cfqq_must_dispatch(cfqq); |
| 917 | cfq_mark_cfqq_wait_request(cfqq); | 901 | cfq_mark_cfqq_wait_request(cfqq); |
| 918 | 902 | ||
| 919 | if (!timer_pending(&cfqd->idle_slice_timer)) { | 903 | sl = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); |
| 920 | unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); | 904 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); |
| 921 | |||
| 922 | cfqd->idle_slice_timer.expires = jiffies + slice_left; | ||
| 923 | add_timer(&cfqd->idle_slice_timer); | ||
| 924 | } | ||
| 925 | |||
| 926 | return 1; | 905 | return 1; |
| 927 | } | 906 | } |
| 928 | 907 | ||
| @@ -1006,9 +985,6 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
| 1006 | if (!cfqq) | 985 | if (!cfqq) |
| 1007 | goto new_queue; | 986 | goto new_queue; |
| 1008 | 987 | ||
| 1009 | if (cfq_cfqq_expired(cfqq)) | ||
| 1010 | goto new_queue; | ||
| 1011 | |||
| 1012 | /* | 988 | /* |
| 1013 | * slice has expired | 989 | * slice has expired |
| 1014 | */ | 990 | */ |
| @@ -1181,10 +1157,8 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
| 1181 | BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); | 1157 | BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); |
| 1182 | BUG_ON(cfq_cfqq_on_rr(cfqq)); | 1158 | BUG_ON(cfq_cfqq_on_rr(cfqq)); |
| 1183 | 1159 | ||
| 1184 | if (unlikely(cfqd->active_queue == cfqq)) { | 1160 | if (unlikely(cfqd->active_queue == cfqq)) |
| 1185 | __cfq_slice_expired(cfqd, cfqq, 0); | 1161 | __cfq_slice_expired(cfqd, cfqq, 0); |
| 1186 | cfq_schedule_dispatch(cfqd); | ||
| 1187 | } | ||
| 1188 | 1162 | ||
| 1189 | cfq_put_cfqd(cfqq->cfqd); | 1163 | cfq_put_cfqd(cfqq->cfqd); |
| 1190 | 1164 | ||
| @@ -1245,10 +1219,8 @@ static void cfq_exit_single_io_context(struct cfq_io_context *cic) | |||
| 1245 | 1219 | ||
| 1246 | spin_lock(q->queue_lock); | 1220 | spin_lock(q->queue_lock); |
| 1247 | 1221 | ||
| 1248 | if (unlikely(cic->cfqq == cfqd->active_queue)) { | 1222 | if (unlikely(cic->cfqq == cfqd->active_queue)) |
| 1249 | __cfq_slice_expired(cfqd, cic->cfqq, 0); | 1223 | __cfq_slice_expired(cfqd, cic->cfqq, 0); |
| 1250 | cfq_schedule_dispatch(cfqd); | ||
| 1251 | } | ||
| 1252 | 1224 | ||
| 1253 | cfq_put_queue(cic->cfqq); | 1225 | cfq_put_queue(cic->cfqq); |
| 1254 | cic->cfqq = NULL; | 1226 | cic->cfqq = NULL; |
| @@ -1715,10 +1687,7 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) | |||
| 1715 | cfqq->service_last = now; | 1687 | cfqq->service_last = now; |
| 1716 | cfq_resort_rr_list(cfqq, 0); | 1688 | cfq_resort_rr_list(cfqq, 0); |
| 1717 | } | 1689 | } |
| 1718 | if (cfq_cfqq_expired(cfqq)) { | 1690 | cfq_schedule_dispatch(cfqd); |
| 1719 | __cfq_slice_expired(cfqd, cfqq, 0); | ||
| 1720 | cfq_schedule_dispatch(cfqd); | ||
| 1721 | } | ||
| 1722 | } | 1691 | } |
| 1723 | 1692 | ||
| 1724 | if (cfq_crq_is_sync(crq)) | 1693 | if (cfq_crq_is_sync(crq)) |
