Commit 2025eb1f authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] cfq direct io alias problem

This is a fix for when we encounter an alias during insert. When that
happens we move the request to dispatch, but it may happen that this
request is also the ->last_merge hint. So we may attempt to merge with
this later, when it's either in progress or already freed. Rearrange the
logic a bit so we clear the merge hint there as well. It looks more
complex than it is, the only real code change is the addition of a
cfq_remove_merge_hints() in cfq_dispatch_sort().
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 73989a76
...@@ -60,6 +60,8 @@ struct cfq_data { ...@@ -60,6 +60,8 @@ struct cfq_data {
mempool_t *crq_pool; mempool_t *crq_pool;
request_queue_t *queue;
/* /*
* tunables * tunables
*/ */
...@@ -95,7 +97,8 @@ struct cfq_rq { ...@@ -95,7 +97,8 @@ struct cfq_rq {
static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq); static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq);
static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid); static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid);
static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq); static void cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq);
/* /*
* lots of deadline iosched dupes, can be abstracted later... * lots of deadline iosched dupes, can be abstracted later...
...@@ -212,8 +215,7 @@ cfq_add_crq_rb(struct cfq_data *cfqd, struct cfq_queue *cfqq,struct cfq_rq *crq) ...@@ -212,8 +215,7 @@ cfq_add_crq_rb(struct cfq_data *cfqd, struct cfq_queue *cfqq,struct cfq_rq *crq)
return; return;
} }
cfq_del_crq_rb(cfqq, __alias); cfq_dispatch_sort(cfqd, cfqq, __alias);
cfq_dispatch_sort(cfqd->dispatch, __alias);
goto retry; goto retry;
} }
...@@ -327,11 +329,16 @@ cfq_merged_requests(request_queue_t *q, struct request *req, ...@@ -327,11 +329,16 @@ cfq_merged_requests(request_queue_t *q, struct request *req,
cfq_remove_request(q, next); cfq_remove_request(q, next);
} }
static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq) static void
cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq)
{ {
struct list_head *entry = head; struct list_head *head = cfqd->dispatch, *entry = head;
struct request *__rq; struct request *__rq;
cfq_del_crq_rb(cfqq, crq);
cfq_remove_merge_hints(cfqd->queue, crq);
if (!list_empty(head)) { if (!list_empty(head)) {
__rq = list_entry_rq(head->next); __rq = list_entry_rq(head->next);
...@@ -358,9 +365,7 @@ __cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd, ...@@ -358,9 +365,7 @@ __cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd,
{ {
struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list)); struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list));
cfq_del_crq_rb(cfqq, crq); cfq_dispatch_sort(cfqd, cfqq, crq);
cfq_remove_merge_hints(q, crq);
cfq_dispatch_sort(cfqd->dispatch, crq);
} }
static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd) static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd)
...@@ -668,6 +673,7 @@ static int cfq_init(request_queue_t *q, elevator_t *e) ...@@ -668,6 +673,7 @@ static int cfq_init(request_queue_t *q, elevator_t *e)
cfqd->dispatch = &q->queue_head; cfqd->dispatch = &q->queue_head;
e->elevator_data = cfqd; e->elevator_data = cfqd;
cfqd->queue = q;
/* /*
* just set it to some high value, we want anyone to be able to queue * just set it to some high value, we want anyone to be able to queue
......
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