Commit 7e843937 authored by Jens Axboe's avatar Jens Axboe

[PATCH] deadline ioscheduler bug fixes

Cleaner fix for the ioscheduler:

- Problem with alias request, the new request gets lost.
- Must always clear merge hash in move_to_dispatch()
parent 15f1049d
...@@ -98,6 +98,8 @@ struct deadline_rq { ...@@ -98,6 +98,8 @@ struct deadline_rq {
unsigned long expires; unsigned long expires;
}; };
static inline void deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq);
static kmem_cache_t *drq_pool; static kmem_cache_t *drq_pool;
#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) #define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private)
...@@ -189,26 +191,22 @@ __deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) ...@@ -189,26 +191,22 @@ __deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
return 0; return 0;
} }
static int static void
deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
{ {
struct deadline_rq *__alias; struct deadline_rq *__alias;
drq->rb_key = rq_rb_key(drq->request); drq->rb_key = rq_rb_key(drq->request);
retry:
__alias = __deadline_add_drq_rb(dd, drq); __alias = __deadline_add_drq_rb(dd, drq);
if (!__alias) { if (!__alias) {
rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
return 0; return;
} }
/* deadline_move_to_dispatch(dd, __alias);
* this should not typically happen, but if it does simply chain goto retry;
* the two requests. then they will be moved to the dispatch list
* at the same time
*/
list_add(&drq->request->queuelist, &__alias->request->queuelist);
return 1;
} }
static inline void static inline void
...@@ -276,13 +274,12 @@ deadline_add_request(struct deadline_data *dd, struct deadline_rq *drq) ...@@ -276,13 +274,12 @@ deadline_add_request(struct deadline_data *dd, struct deadline_rq *drq)
{ {
const int data_dir = rq_data_dir(drq->request); const int data_dir = rq_data_dir(drq->request);
if (!deadline_add_drq_rb(dd, drq)) { deadline_add_drq_rb(dd, drq);
/* /*
* set expire time (only used for reads) and add to fifo list * set expire time (only used for reads) and add to fifo list
*/ */
drq->expires = jiffies + dd->fifo_expire[data_dir]; drq->expires = jiffies + dd->fifo_expire[data_dir];
list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
}
} }
/* /*
...@@ -425,6 +422,12 @@ deadline_merged_requests(request_queue_t *q, struct request *req, ...@@ -425,6 +422,12 @@ deadline_merged_requests(request_queue_t *q, struct request *req,
static inline void static inline void
deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq) deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
{ {
request_queue_t *q = drq->request->q;
if (q->last_merge == &drq->request->queuelist)
q->last_merge = NULL;
deadline_del_drq_hash(drq);
deadline_del_drq_rb(dd, drq); deadline_del_drq_rb(dd, drq);
list_del_init(&drq->fifo); list_del_init(&drq->fifo);
list_add_tail(&drq->request->queuelist, dd->dispatch); list_add_tail(&drq->request->queuelist, dd->dispatch);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment