# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/18 09:50:41-07:00 axboe@suse.de # [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: Linus Torvalds # # drivers/block/cfq-iosched.c # 2004/06/17 10:37:34-07:00 axboe@suse.de +14 -8 # cfq direct io alias problem # diff -Nru a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c --- a/drivers/block/cfq-iosched.c 2004-06-18 11:44:09 -07:00 +++ b/drivers/block/cfq-iosched.c 2004-06-18 11:44:09 -07:00 @@ -60,6 +60,8 @@ mempool_t *crq_pool; + request_queue_t *queue; + /* * tunables */ @@ -95,7 +97,8 @@ 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 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... @@ -212,8 +215,7 @@ return; } - cfq_del_crq_rb(cfqq, __alias); - cfq_dispatch_sort(cfqd->dispatch, __alias); + cfq_dispatch_sort(cfqd, cfqq, __alias); goto retry; } @@ -327,11 +329,16 @@ 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; + cfq_del_crq_rb(cfqq, crq); + cfq_remove_merge_hints(cfqd->queue, crq); + if (!list_empty(head)) { __rq = list_entry_rq(head->next); @@ -358,9 +365,7 @@ { struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list)); - cfq_del_crq_rb(cfqq, crq); - cfq_remove_merge_hints(q, crq); - cfq_dispatch_sort(cfqd->dispatch, crq); + cfq_dispatch_sort(cfqd, cfqq, crq); } static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd) @@ -668,6 +673,7 @@ cfqd->dispatch = &q->queue_head; e->elevator_data = cfqd; + cfqd->queue = q; /* * just set it to some high value, we want anyone to be able to queue