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 74fae2daf87..c8dbe38c81c 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)) |