aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2005-11-10 02:49:19 -0500
committerJens Axboe <axboe@nelson.home.kernel.dk>2005-11-12 04:55:51 -0500
commit1b5ed5e1f1315e37380e55102f58bcae3344d2a7 (patch)
tree785dc9675e2f22b60017030063ba103740c72f16 /block/cfq-iosched.c
parent407df2aa29a33fe16f6ee4bac8cdfa414783b9f1 (diff)
[BLOCK] cfq-iosched: cfq forced dispatching fix
cfq forced dispatching might not return all requests on the queue. This bug can hang elevator switchinig and corrupt request ordering during flush sequence. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ecacca9c877e..452538644bce 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -999,7 +999,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
999/* 999/*
1000 * get next queue for service 1000 * get next queue for service
1001 */ 1001 */
1002static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) 1002static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
1003{ 1003{
1004 unsigned long now = jiffies; 1004 unsigned long now = jiffies;
1005 struct cfq_queue *cfqq; 1005 struct cfq_queue *cfqq;
@@ -1023,7 +1023,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
1023 */ 1023 */
1024 if (!RB_EMPTY(&cfqq->sort_list)) 1024 if (!RB_EMPTY(&cfqq->sort_list))
1025 goto keep_queue; 1025 goto keep_queue;
1026 else if (!force && cfq_cfqq_class_sync(cfqq) && 1026 else if (cfq_cfqq_class_sync(cfqq) &&
1027 time_before(now, cfqq->slice_end)) { 1027 time_before(now, cfqq->slice_end)) {
1028 if (cfq_arm_slice_timer(cfqd, cfqq)) 1028 if (cfq_arm_slice_timer(cfqd, cfqq))
1029 return NULL; 1029 return NULL;
@@ -1092,6 +1092,42 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1092} 1092}
1093 1093
1094static int 1094static int
1095cfq_forced_dispatch_cfqqs(struct list_head *list)
1096{
1097 int dispatched = 0;
1098 struct cfq_queue *cfqq, *next;
1099 struct cfq_rq *crq;
1100
1101 list_for_each_entry_safe(cfqq, next, list, cfq_list) {
1102 while ((crq = cfqq->next_crq)) {
1103 cfq_dispatch_insert(cfqq->cfqd->queue, crq);
1104 dispatched++;
1105 }
1106 BUG_ON(!list_empty(&cfqq->fifo));
1107 }
1108 return dispatched;
1109}
1110
1111static int
1112cfq_forced_dispatch(struct cfq_data *cfqd)
1113{
1114 int i, dispatched = 0;
1115
1116 for (i = 0; i < CFQ_PRIO_LISTS; i++)
1117 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->rr_list[i]);
1118
1119 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->busy_rr);
1120 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr);
1121 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->idle_rr);
1122
1123 cfq_slice_expired(cfqd, 0);
1124
1125 BUG_ON(cfqd->busy_queues);
1126
1127 return dispatched;
1128}
1129
1130static int
1095cfq_dispatch_requests(request_queue_t *q, int force) 1131cfq_dispatch_requests(request_queue_t *q, int force)
1096{ 1132{
1097 struct cfq_data *cfqd = q->elevator->elevator_data; 1133 struct cfq_data *cfqd = q->elevator->elevator_data;
@@ -1100,7 +1136,10 @@ cfq_dispatch_requests(request_queue_t *q, int force)
1100 if (!cfqd->busy_queues) 1136 if (!cfqd->busy_queues)
1101 return 0; 1137 return 0;
1102 1138
1103 cfqq = cfq_select_queue(cfqd, force); 1139 if (unlikely(force))
1140 return cfq_forced_dispatch(cfqd);
1141
1142 cfqq = cfq_select_queue(cfqd);
1104 if (cfqq) { 1143 if (cfqq) {
1105 int max_dispatch; 1144 int max_dispatch;
1106 1145
@@ -1115,12 +1154,9 @@ cfq_dispatch_requests(request_queue_t *q, int force)
1115 cfq_clear_cfqq_wait_request(cfqq); 1154 cfq_clear_cfqq_wait_request(cfqq);
1116 del_timer(&cfqd->idle_slice_timer); 1155 del_timer(&cfqd->idle_slice_timer);
1117 1156
1118 if (!force) { 1157 max_dispatch = cfqd->cfq_quantum;
1119 max_dispatch = cfqd->cfq_quantum; 1158 if (cfq_class_idle(cfqq))
1120 if (cfq_class_idle(cfqq)) 1159 max_dispatch = 1;
1121 max_dispatch = 1;
1122 } else
1123 max_dispatch = INT_MAX;
1124 1160
1125 return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); 1161 return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
1126 } 1162 }