Skip to content

Commit

Permalink
cfq-iosched: fix alias + front merge bug
Browse files Browse the repository at this point in the history
There's a really rare and obscure bug in CFQ, that causes a crash in
cfq_dispatch_insert() due to rq == NULL.  One example of the resulting
oops is seen here:

	http://lkml.org/lkml/2007/4/15/41

Neil correctly diagnosed the situation for how this can happen: if two
concurrent requests with the exact same sector number (due to direct IO
or aliasing between MD and the raw device access), the alias handling
will add the request to the sortlist, but next_rq remains NULL.

Read the more complete analysis at:

	http://lkml.org/lkml/2007/4/25/57

This looks like it requires md to trigger, even though it should
potentially be possible to due with O_DIRECT (at least if you edit the
kernel and doctor some of the unplug calls).

The fix is to move the ->next_rq update to when we add a request to the
rbtree. Then we remove the possibility for a request to exist in the
rbtree code, but not have ->next_rq correctly updated.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Jens Axboe authored and Linus Torvalds committed Apr 25, 2007
1 parent a23cf14 commit 5044eed
Showing 1 changed file with 6 additions and 6 deletions.
12 changes: 6 additions & 6 deletions block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,12 @@ static void cfq_add_rq_rb(struct request *rq)

if (!cfq_cfqq_on_rr(cfqq))
cfq_add_cfqq_rr(cfqd, cfqq);

/*
* check if this request is a better next-serve candidate
*/
cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq);
BUG_ON(!cfqq->next_rq);
}

static inline void
Expand Down Expand Up @@ -1638,12 +1644,6 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
if (rq_is_meta(rq))
cfqq->meta_pending++;

/*
* check if this request is a better next-serve candidate)) {
*/
cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq);
BUG_ON(!cfqq->next_rq);

/*
* we never wait for an async request and we don't allow preemption
* of an async request. so just return early
Expand Down

0 comments on commit 5044eed

Please sign in to comment.