diff options
author | Jens Axboe <axboe@suse.de> | 2005-10-20 10:42:29 -0400 |
---|---|---|
committer | Jens Axboe <axboe@nelson.home.kernel.dk> | 2005-10-28 02:45:08 -0400 |
commit | b4878f245ec8e168cdd1f170f823a750b7dd4af5 (patch) | |
tree | de784c2a7e1174e4843807998f0356bf92ee78be /drivers/block/as-iosched.c | |
parent | d9ebb192aa13a026edc6faff137dcb14f2c91731 (diff) |
[PATCH] 02/05: update ioscheds to use generic dispatch queue
This patch updates all four ioscheds to use generic dispatch
queue. There's one behavior change in as-iosched.
* In as-iosched, when force dispatching
(ELEVATOR_INSERT_BACK), batch_data_dir is reset to REQ_SYNC
and changed_batch and new_batch are cleared to zero. This
prevernts AS from doing incorrect update_write_batch after
the forced dispatched requests are finished.
* In cfq-iosched, cfqd->rq_in_driver currently counts the
number of activated (removed) requests to determine
whether queue-kicking is needed and cfq_max_depth has been
reached. With generic dispatch queue, I think counting
the number of dispatched requests would be more appropriate.
* cfq_max_depth can be lowered to 1 again.
Original from Tejun Heo, modified version applied.
Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'drivers/block/as-iosched.c')
-rw-r--r-- | drivers/block/as-iosched.c | 290 |
1 files changed, 85 insertions, 205 deletions
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 95c0a3690b0f..1775ffe9edc7 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c | |||
@@ -98,7 +98,6 @@ struct as_data { | |||
98 | 98 | ||
99 | struct as_rq *next_arq[2]; /* next in sort order */ | 99 | struct as_rq *next_arq[2]; /* next in sort order */ |
100 | sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ | 100 | sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ |
101 | struct list_head *dispatch; /* driver dispatch queue */ | ||
102 | struct list_head *hash; /* request hash */ | 101 | struct list_head *hash; /* request hash */ |
103 | 102 | ||
104 | unsigned long exit_prob; /* probability a task will exit while | 103 | unsigned long exit_prob; /* probability a task will exit while |
@@ -239,6 +238,25 @@ static struct io_context *as_get_io_context(void) | |||
239 | return ioc; | 238 | return ioc; |
240 | } | 239 | } |
241 | 240 | ||
241 | static void as_put_io_context(struct as_rq *arq) | ||
242 | { | ||
243 | struct as_io_context *aic; | ||
244 | |||
245 | if (unlikely(!arq->io_context)) | ||
246 | return; | ||
247 | |||
248 | aic = arq->io_context->aic; | ||
249 | |||
250 | if (arq->is_sync == REQ_SYNC && aic) { | ||
251 | spin_lock(&aic->lock); | ||
252 | set_bit(AS_TASK_IORUNNING, &aic->state); | ||
253 | aic->last_end_request = jiffies; | ||
254 | spin_unlock(&aic->lock); | ||
255 | } | ||
256 | |||
257 | put_io_context(arq->io_context); | ||
258 | } | ||
259 | |||
242 | /* | 260 | /* |
243 | * the back merge hash support functions | 261 | * the back merge hash support functions |
244 | */ | 262 | */ |
@@ -950,23 +968,12 @@ static void as_completed_request(request_queue_t *q, struct request *rq) | |||
950 | 968 | ||
951 | WARN_ON(!list_empty(&rq->queuelist)); | 969 | WARN_ON(!list_empty(&rq->queuelist)); |
952 | 970 | ||
953 | if (arq->state == AS_RQ_PRESCHED) { | ||
954 | WARN_ON(arq->io_context); | ||
955 | goto out; | ||
956 | } | ||
957 | |||
958 | if (arq->state == AS_RQ_MERGED) | ||
959 | goto out_ioc; | ||
960 | |||
961 | if (arq->state != AS_RQ_REMOVED) { | 971 | if (arq->state != AS_RQ_REMOVED) { |
962 | printk("arq->state %d\n", arq->state); | 972 | printk("arq->state %d\n", arq->state); |
963 | WARN_ON(1); | 973 | WARN_ON(1); |
964 | goto out; | 974 | goto out; |
965 | } | 975 | } |
966 | 976 | ||
967 | if (!blk_fs_request(rq)) | ||
968 | goto out; | ||
969 | |||
970 | if (ad->changed_batch && ad->nr_dispatched == 1) { | 977 | if (ad->changed_batch && ad->nr_dispatched == 1) { |
971 | kblockd_schedule_work(&ad->antic_work); | 978 | kblockd_schedule_work(&ad->antic_work); |
972 | ad->changed_batch = 0; | 979 | ad->changed_batch = 0; |
@@ -1001,21 +1008,7 @@ static void as_completed_request(request_queue_t *q, struct request *rq) | |||
1001 | } | 1008 | } |
1002 | } | 1009 | } |
1003 | 1010 | ||
1004 | out_ioc: | 1011 | as_put_io_context(arq); |
1005 | if (!arq->io_context) | ||
1006 | goto out; | ||
1007 | |||
1008 | if (arq->is_sync == REQ_SYNC) { | ||
1009 | struct as_io_context *aic = arq->io_context->aic; | ||
1010 | if (aic) { | ||
1011 | spin_lock(&aic->lock); | ||
1012 | set_bit(AS_TASK_IORUNNING, &aic->state); | ||
1013 | aic->last_end_request = jiffies; | ||
1014 | spin_unlock(&aic->lock); | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | put_io_context(arq->io_context); | ||
1019 | out: | 1012 | out: |
1020 | arq->state = AS_RQ_POSTSCHED; | 1013 | arq->state = AS_RQ_POSTSCHED; |
1021 | } | 1014 | } |
@@ -1052,68 +1045,6 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq) | |||
1052 | } | 1045 | } |
1053 | 1046 | ||
1054 | /* | 1047 | /* |
1055 | * as_remove_dispatched_request is called to remove a request which has gone | ||
1056 | * to the dispatch list. | ||
1057 | */ | ||
1058 | static void as_remove_dispatched_request(request_queue_t *q, struct request *rq) | ||
1059 | { | ||
1060 | struct as_rq *arq = RQ_DATA(rq); | ||
1061 | struct as_io_context *aic; | ||
1062 | |||
1063 | if (!arq) { | ||
1064 | WARN_ON(1); | ||
1065 | return; | ||
1066 | } | ||
1067 | |||
1068 | WARN_ON(arq->state != AS_RQ_DISPATCHED); | ||
1069 | WARN_ON(ON_RB(&arq->rb_node)); | ||
1070 | if (arq->io_context && arq->io_context->aic) { | ||
1071 | aic = arq->io_context->aic; | ||
1072 | if (aic) { | ||
1073 | WARN_ON(!atomic_read(&aic->nr_dispatched)); | ||
1074 | atomic_dec(&aic->nr_dispatched); | ||
1075 | } | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | /* | ||
1080 | * as_remove_request is called when a driver has finished with a request. | ||
1081 | * This should be only called for dispatched requests, but for some reason | ||
1082 | * a POWER4 box running hwscan it does not. | ||
1083 | */ | ||
1084 | static void as_remove_request(request_queue_t *q, struct request *rq) | ||
1085 | { | ||
1086 | struct as_rq *arq = RQ_DATA(rq); | ||
1087 | |||
1088 | if (unlikely(arq->state == AS_RQ_NEW)) | ||
1089 | goto out; | ||
1090 | |||
1091 | if (ON_RB(&arq->rb_node)) { | ||
1092 | if (arq->state != AS_RQ_QUEUED) { | ||
1093 | printk("arq->state %d\n", arq->state); | ||
1094 | WARN_ON(1); | ||
1095 | goto out; | ||
1096 | } | ||
1097 | /* | ||
1098 | * We'll lose the aliased request(s) here. I don't think this | ||
1099 | * will ever happen, but if it does, hopefully someone will | ||
1100 | * report it. | ||
1101 | */ | ||
1102 | WARN_ON(!list_empty(&rq->queuelist)); | ||
1103 | as_remove_queued_request(q, rq); | ||
1104 | } else { | ||
1105 | if (arq->state != AS_RQ_DISPATCHED) { | ||
1106 | printk("arq->state %d\n", arq->state); | ||
1107 | WARN_ON(1); | ||
1108 | goto out; | ||
1109 | } | ||
1110 | as_remove_dispatched_request(q, rq); | ||
1111 | } | ||
1112 | out: | ||
1113 | arq->state = AS_RQ_REMOVED; | ||
1114 | } | ||
1115 | |||
1116 | /* | ||
1117 | * as_fifo_expired returns 0 if there are no expired reads on the fifo, | 1048 | * as_fifo_expired returns 0 if there are no expired reads on the fifo, |
1118 | * 1 otherwise. It is ratelimited so that we only perform the check once per | 1049 | * 1 otherwise. It is ratelimited so that we only perform the check once per |
1119 | * `fifo_expire' interval. Otherwise a large number of expired requests | 1050 | * `fifo_expire' interval. Otherwise a large number of expired requests |
@@ -1165,7 +1096,6 @@ static inline int as_batch_expired(struct as_data *ad) | |||
1165 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | 1096 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) |
1166 | { | 1097 | { |
1167 | struct request *rq = arq->request; | 1098 | struct request *rq = arq->request; |
1168 | struct list_head *insert; | ||
1169 | const int data_dir = arq->is_sync; | 1099 | const int data_dir = arq->is_sync; |
1170 | 1100 | ||
1171 | BUG_ON(!ON_RB(&arq->rb_node)); | 1101 | BUG_ON(!ON_RB(&arq->rb_node)); |
@@ -1198,13 +1128,13 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | |||
1198 | /* | 1128 | /* |
1199 | * take it off the sort and fifo list, add to dispatch queue | 1129 | * take it off the sort and fifo list, add to dispatch queue |
1200 | */ | 1130 | */ |
1201 | insert = ad->dispatch->prev; | ||
1202 | |||
1203 | while (!list_empty(&rq->queuelist)) { | 1131 | while (!list_empty(&rq->queuelist)) { |
1204 | struct request *__rq = list_entry_rq(rq->queuelist.next); | 1132 | struct request *__rq = list_entry_rq(rq->queuelist.next); |
1205 | struct as_rq *__arq = RQ_DATA(__rq); | 1133 | struct as_rq *__arq = RQ_DATA(__rq); |
1206 | 1134 | ||
1207 | list_move_tail(&__rq->queuelist, ad->dispatch); | 1135 | list_del(&__rq->queuelist); |
1136 | |||
1137 | elv_dispatch_add_tail(ad->q, __rq); | ||
1208 | 1138 | ||
1209 | if (__arq->io_context && __arq->io_context->aic) | 1139 | if (__arq->io_context && __arq->io_context->aic) |
1210 | atomic_inc(&__arq->io_context->aic->nr_dispatched); | 1140 | atomic_inc(&__arq->io_context->aic->nr_dispatched); |
@@ -1218,7 +1148,8 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | |||
1218 | as_remove_queued_request(ad->q, rq); | 1148 | as_remove_queued_request(ad->q, rq); |
1219 | WARN_ON(arq->state != AS_RQ_QUEUED); | 1149 | WARN_ON(arq->state != AS_RQ_QUEUED); |
1220 | 1150 | ||
1221 | list_add(&rq->queuelist, insert); | 1151 | elv_dispatch_sort(ad->q, rq); |
1152 | |||
1222 | arq->state = AS_RQ_DISPATCHED; | 1153 | arq->state = AS_RQ_DISPATCHED; |
1223 | if (arq->io_context && arq->io_context->aic) | 1154 | if (arq->io_context && arq->io_context->aic) |
1224 | atomic_inc(&arq->io_context->aic->nr_dispatched); | 1155 | atomic_inc(&arq->io_context->aic->nr_dispatched); |
@@ -1230,12 +1161,42 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | |||
1230 | * read/write expire, batch expire, etc, and moves it to the dispatch | 1161 | * read/write expire, batch expire, etc, and moves it to the dispatch |
1231 | * queue. Returns 1 if a request was found, 0 otherwise. | 1162 | * queue. Returns 1 if a request was found, 0 otherwise. |
1232 | */ | 1163 | */ |
1233 | static int as_dispatch_request(struct as_data *ad) | 1164 | static int as_dispatch_request(request_queue_t *q, int force) |
1234 | { | 1165 | { |
1166 | struct as_data *ad = q->elevator->elevator_data; | ||
1235 | struct as_rq *arq; | 1167 | struct as_rq *arq; |
1236 | const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]); | 1168 | const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]); |
1237 | const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]); | 1169 | const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]); |
1238 | 1170 | ||
1171 | if (unlikely(force)) { | ||
1172 | /* | ||
1173 | * Forced dispatch, accounting is useless. Reset | ||
1174 | * accounting states and dump fifo_lists. Note that | ||
1175 | * batch_data_dir is reset to REQ_SYNC to avoid | ||
1176 | * screwing write batch accounting as write batch | ||
1177 | * accounting occurs on W->R transition. | ||
1178 | */ | ||
1179 | int dispatched = 0; | ||
1180 | |||
1181 | ad->batch_data_dir = REQ_SYNC; | ||
1182 | ad->changed_batch = 0; | ||
1183 | ad->new_batch = 0; | ||
1184 | |||
1185 | while (ad->next_arq[REQ_SYNC]) { | ||
1186 | as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); | ||
1187 | dispatched++; | ||
1188 | } | ||
1189 | ad->last_check_fifo[REQ_SYNC] = jiffies; | ||
1190 | |||
1191 | while (ad->next_arq[REQ_ASYNC]) { | ||
1192 | as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); | ||
1193 | dispatched++; | ||
1194 | } | ||
1195 | ad->last_check_fifo[REQ_ASYNC] = jiffies; | ||
1196 | |||
1197 | return dispatched; | ||
1198 | } | ||
1199 | |||
1239 | /* Signal that the write batch was uncontended, so we can't time it */ | 1200 | /* Signal that the write batch was uncontended, so we can't time it */ |
1240 | if (ad->batch_data_dir == REQ_ASYNC && !reads) { | 1201 | if (ad->batch_data_dir == REQ_ASYNC && !reads) { |
1241 | if (ad->current_write_count == 0 || !writes) | 1202 | if (ad->current_write_count == 0 || !writes) |
@@ -1359,20 +1320,6 @@ fifo_expired: | |||
1359 | return 1; | 1320 | return 1; |
1360 | } | 1321 | } |
1361 | 1322 | ||
1362 | static struct request *as_next_request(request_queue_t *q) | ||
1363 | { | ||
1364 | struct as_data *ad = q->elevator->elevator_data; | ||
1365 | struct request *rq = NULL; | ||
1366 | |||
1367 | /* | ||
1368 | * if there are still requests on the dispatch queue, grab the first | ||
1369 | */ | ||
1370 | if (!list_empty(ad->dispatch) || as_dispatch_request(ad)) | ||
1371 | rq = list_entry_rq(ad->dispatch->next); | ||
1372 | |||
1373 | return rq; | ||
1374 | } | ||
1375 | |||
1376 | /* | 1323 | /* |
1377 | * Add arq to a list behind alias | 1324 | * Add arq to a list behind alias |
1378 | */ | 1325 | */ |
@@ -1410,11 +1357,19 @@ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alia | |||
1410 | /* | 1357 | /* |
1411 | * add arq to rbtree and fifo | 1358 | * add arq to rbtree and fifo |
1412 | */ | 1359 | */ |
1413 | static void as_add_request(struct as_data *ad, struct as_rq *arq) | 1360 | static void as_add_request(request_queue_t *q, struct request *rq) |
1414 | { | 1361 | { |
1362 | struct as_data *ad = q->elevator->elevator_data; | ||
1363 | struct as_rq *arq = RQ_DATA(rq); | ||
1415 | struct as_rq *alias; | 1364 | struct as_rq *alias; |
1416 | int data_dir; | 1365 | int data_dir; |
1417 | 1366 | ||
1367 | if (arq->state != AS_RQ_PRESCHED) { | ||
1368 | printk("arq->state: %d\n", arq->state); | ||
1369 | WARN_ON(1); | ||
1370 | } | ||
1371 | arq->state = AS_RQ_NEW; | ||
1372 | |||
1418 | if (rq_data_dir(arq->request) == READ | 1373 | if (rq_data_dir(arq->request) == READ |
1419 | || current->flags&PF_SYNCWRITE) | 1374 | || current->flags&PF_SYNCWRITE) |
1420 | arq->is_sync = 1; | 1375 | arq->is_sync = 1; |
@@ -1463,96 +1418,24 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq) | |||
1463 | arq->state = AS_RQ_QUEUED; | 1418 | arq->state = AS_RQ_QUEUED; |
1464 | } | 1419 | } |
1465 | 1420 | ||
1466 | static void as_deactivate_request(request_queue_t *q, struct request *rq) | 1421 | static void as_activate_request(request_queue_t *q, struct request *rq) |
1467 | { | 1422 | { |
1468 | struct as_data *ad = q->elevator->elevator_data; | ||
1469 | struct as_rq *arq = RQ_DATA(rq); | 1423 | struct as_rq *arq = RQ_DATA(rq); |
1470 | 1424 | ||
1471 | if (arq) { | 1425 | WARN_ON(arq->state != AS_RQ_DISPATCHED); |
1472 | if (arq->state == AS_RQ_REMOVED) { | 1426 | arq->state = AS_RQ_REMOVED; |
1473 | arq->state = AS_RQ_DISPATCHED; | 1427 | if (arq->io_context && arq->io_context->aic) |
1474 | if (arq->io_context && arq->io_context->aic) | 1428 | atomic_dec(&arq->io_context->aic->nr_dispatched); |
1475 | atomic_inc(&arq->io_context->aic->nr_dispatched); | ||
1476 | } | ||
1477 | } else | ||
1478 | WARN_ON(blk_fs_request(rq) | ||
1479 | && (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) ); | ||
1480 | |||
1481 | /* Stop anticipating - let this request get through */ | ||
1482 | as_antic_stop(ad); | ||
1483 | } | ||
1484 | |||
1485 | /* | ||
1486 | * requeue the request. The request has not been completed, nor is it a | ||
1487 | * new request, so don't touch accounting. | ||
1488 | */ | ||
1489 | static void as_requeue_request(request_queue_t *q, struct request *rq) | ||
1490 | { | ||
1491 | as_deactivate_request(q, rq); | ||
1492 | list_add(&rq->queuelist, &q->queue_head); | ||
1493 | } | ||
1494 | |||
1495 | /* | ||
1496 | * Account a request that is inserted directly onto the dispatch queue. | ||
1497 | * arq->io_context->aic->nr_dispatched should not need to be incremented | ||
1498 | * because only new requests should come through here: requeues go through | ||
1499 | * our explicit requeue handler. | ||
1500 | */ | ||
1501 | static void as_account_queued_request(struct as_data *ad, struct request *rq) | ||
1502 | { | ||
1503 | if (blk_fs_request(rq)) { | ||
1504 | struct as_rq *arq = RQ_DATA(rq); | ||
1505 | arq->state = AS_RQ_DISPATCHED; | ||
1506 | ad->nr_dispatched++; | ||
1507 | } | ||
1508 | } | 1429 | } |
1509 | 1430 | ||
1510 | static void | 1431 | static void as_deactivate_request(request_queue_t *q, struct request *rq) |
1511 | as_insert_request(request_queue_t *q, struct request *rq, int where) | ||
1512 | { | 1432 | { |
1513 | struct as_data *ad = q->elevator->elevator_data; | ||
1514 | struct as_rq *arq = RQ_DATA(rq); | 1433 | struct as_rq *arq = RQ_DATA(rq); |
1515 | 1434 | ||
1516 | if (arq) { | 1435 | WARN_ON(arq->state != AS_RQ_REMOVED); |
1517 | if (arq->state != AS_RQ_PRESCHED) { | 1436 | arq->state = AS_RQ_DISPATCHED; |
1518 | printk("arq->state: %d\n", arq->state); | 1437 | if (arq->io_context && arq->io_context->aic) |
1519 | WARN_ON(1); | 1438 | atomic_inc(&arq->io_context->aic->nr_dispatched); |
1520 | } | ||
1521 | arq->state = AS_RQ_NEW; | ||
1522 | } | ||
1523 | |||
1524 | /* barriers must flush the reorder queue */ | ||
1525 | if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) | ||
1526 | && where == ELEVATOR_INSERT_SORT)) { | ||
1527 | WARN_ON(1); | ||
1528 | where = ELEVATOR_INSERT_BACK; | ||
1529 | } | ||
1530 | |||
1531 | switch (where) { | ||
1532 | case ELEVATOR_INSERT_BACK: | ||
1533 | while (ad->next_arq[REQ_SYNC]) | ||
1534 | as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); | ||
1535 | |||
1536 | while (ad->next_arq[REQ_ASYNC]) | ||
1537 | as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); | ||
1538 | |||
1539 | list_add_tail(&rq->queuelist, ad->dispatch); | ||
1540 | as_account_queued_request(ad, rq); | ||
1541 | as_antic_stop(ad); | ||
1542 | break; | ||
1543 | case ELEVATOR_INSERT_FRONT: | ||
1544 | list_add(&rq->queuelist, ad->dispatch); | ||
1545 | as_account_queued_request(ad, rq); | ||
1546 | as_antic_stop(ad); | ||
1547 | break; | ||
1548 | case ELEVATOR_INSERT_SORT: | ||
1549 | BUG_ON(!blk_fs_request(rq)); | ||
1550 | as_add_request(ad, arq); | ||
1551 | break; | ||
1552 | default: | ||
1553 | BUG(); | ||
1554 | return; | ||
1555 | } | ||
1556 | } | 1439 | } |
1557 | 1440 | ||
1558 | /* | 1441 | /* |
@@ -1565,12 +1448,8 @@ static int as_queue_empty(request_queue_t *q) | |||
1565 | { | 1448 | { |
1566 | struct as_data *ad = q->elevator->elevator_data; | 1449 | struct as_data *ad = q->elevator->elevator_data; |
1567 | 1450 | ||
1568 | if (!list_empty(&ad->fifo_list[REQ_ASYNC]) | 1451 | return list_empty(&ad->fifo_list[REQ_ASYNC]) |
1569 | || !list_empty(&ad->fifo_list[REQ_SYNC]) | 1452 | && list_empty(&ad->fifo_list[REQ_SYNC]); |
1570 | || !list_empty(ad->dispatch)) | ||
1571 | return 0; | ||
1572 | |||
1573 | return 1; | ||
1574 | } | 1453 | } |
1575 | 1454 | ||
1576 | static struct request * | 1455 | static struct request * |
@@ -1763,6 +1642,7 @@ as_merged_requests(request_queue_t *q, struct request *req, | |||
1763 | * kill knowledge of next, this one is a goner | 1642 | * kill knowledge of next, this one is a goner |
1764 | */ | 1643 | */ |
1765 | as_remove_queued_request(q, next); | 1644 | as_remove_queued_request(q, next); |
1645 | as_put_io_context(anext); | ||
1766 | 1646 | ||
1767 | anext->state = AS_RQ_MERGED; | 1647 | anext->state = AS_RQ_MERGED; |
1768 | } | 1648 | } |
@@ -1782,7 +1662,7 @@ static void as_work_handler(void *data) | |||
1782 | unsigned long flags; | 1662 | unsigned long flags; |
1783 | 1663 | ||
1784 | spin_lock_irqsave(q->queue_lock, flags); | 1664 | spin_lock_irqsave(q->queue_lock, flags); |
1785 | if (as_next_request(q)) | 1665 | if (!as_queue_empty(q)) |
1786 | q->request_fn(q); | 1666 | q->request_fn(q); |
1787 | spin_unlock_irqrestore(q->queue_lock, flags); | 1667 | spin_unlock_irqrestore(q->queue_lock, flags); |
1788 | } | 1668 | } |
@@ -1797,7 +1677,9 @@ static void as_put_request(request_queue_t *q, struct request *rq) | |||
1797 | return; | 1677 | return; |
1798 | } | 1678 | } |
1799 | 1679 | ||
1800 | if (arq->state != AS_RQ_POSTSCHED && arq->state != AS_RQ_PRESCHED) { | 1680 | if (unlikely(arq->state != AS_RQ_POSTSCHED && |
1681 | arq->state != AS_RQ_PRESCHED && | ||
1682 | arq->state != AS_RQ_MERGED)) { | ||
1801 | printk("arq->state %d\n", arq->state); | 1683 | printk("arq->state %d\n", arq->state); |
1802 | WARN_ON(1); | 1684 | WARN_ON(1); |
1803 | } | 1685 | } |
@@ -1907,7 +1789,6 @@ static int as_init_queue(request_queue_t *q, elevator_t *e) | |||
1907 | INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); | 1789 | INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); |
1908 | ad->sort_list[REQ_SYNC] = RB_ROOT; | 1790 | ad->sort_list[REQ_SYNC] = RB_ROOT; |
1909 | ad->sort_list[REQ_ASYNC] = RB_ROOT; | 1791 | ad->sort_list[REQ_ASYNC] = RB_ROOT; |
1910 | ad->dispatch = &q->queue_head; | ||
1911 | ad->fifo_expire[REQ_SYNC] = default_read_expire; | 1792 | ad->fifo_expire[REQ_SYNC] = default_read_expire; |
1912 | ad->fifo_expire[REQ_ASYNC] = default_write_expire; | 1793 | ad->fifo_expire[REQ_ASYNC] = default_write_expire; |
1913 | ad->antic_expire = default_antic_expire; | 1794 | ad->antic_expire = default_antic_expire; |
@@ -2072,10 +1953,9 @@ static struct elevator_type iosched_as = { | |||
2072 | .elevator_merge_fn = as_merge, | 1953 | .elevator_merge_fn = as_merge, |
2073 | .elevator_merged_fn = as_merged_request, | 1954 | .elevator_merged_fn = as_merged_request, |
2074 | .elevator_merge_req_fn = as_merged_requests, | 1955 | .elevator_merge_req_fn = as_merged_requests, |
2075 | .elevator_next_req_fn = as_next_request, | 1956 | .elevator_dispatch_fn = as_dispatch_request, |
2076 | .elevator_add_req_fn = as_insert_request, | 1957 | .elevator_add_req_fn = as_add_request, |
2077 | .elevator_remove_req_fn = as_remove_request, | 1958 | .elevator_activate_req_fn = as_activate_request, |
2078 | .elevator_requeue_req_fn = as_requeue_request, | ||
2079 | .elevator_deactivate_req_fn = as_deactivate_request, | 1959 | .elevator_deactivate_req_fn = as_deactivate_request, |
2080 | .elevator_queue_empty_fn = as_queue_empty, | 1960 | .elevator_queue_empty_fn = as_queue_empty, |
2081 | .elevator_completed_req_fn = as_completed_request, | 1961 | .elevator_completed_req_fn = as_completed_request, |