aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c151
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);
264CFQ_CFQQ_FNS(fifo_expire); 263CFQ_CFQQ_FNS(fifo_expire);
265CFQ_CFQQ_FNS(idle_window); 264CFQ_CFQQ_FNS(idle_window);
266CFQ_CFQQ_FNS(prio_changed); 265CFQ_CFQQ_FNS(prio_changed);
267CFQ_CFQQ_FNS(expired);
268#undef CFQ_CFQQ_FNS 266#undef CFQ_CFQQ_FNS
269 267
270enum cfq_rq_state_flags { 268enum cfq_rq_state_flags {
@@ -336,7 +334,7 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
336 */ 334 */
337static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) 335static 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 */
745static 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
785static 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
802static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) 850static 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 */
843static 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
881static 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
897static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) 879static 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))