diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5ff4f4850e71..153f6277e5c8 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1986,6 +1986,15 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq) | |||
1986 | int process_refs, new_process_refs; | 1986 | int process_refs, new_process_refs; |
1987 | struct cfq_queue *__cfqq; | 1987 | struct cfq_queue *__cfqq; |
1988 | 1988 | ||
1989 | /* | ||
1990 | * If there are no process references on the new_cfqq, then it is | ||
1991 | * unsafe to follow the ->new_cfqq chain as other cfqq's in the | ||
1992 | * chain may have dropped their last reference (not just their | ||
1993 | * last process reference). | ||
1994 | */ | ||
1995 | if (!cfqq_process_refs(new_cfqq)) | ||
1996 | return; | ||
1997 | |||
1989 | /* Avoid a circular list and skip interim queue merges */ | 1998 | /* Avoid a circular list and skip interim queue merges */ |
1990 | while ((__cfqq = new_cfqq->new_cfqq)) { | 1999 | while ((__cfqq = new_cfqq->new_cfqq)) { |
1991 | if (__cfqq == cfqq) | 2000 | if (__cfqq == cfqq) |
@@ -1994,17 +2003,17 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq) | |||
1994 | } | 2003 | } |
1995 | 2004 | ||
1996 | process_refs = cfqq_process_refs(cfqq); | 2005 | process_refs = cfqq_process_refs(cfqq); |
2006 | new_process_refs = cfqq_process_refs(new_cfqq); | ||
1997 | /* | 2007 | /* |
1998 | * If the process for the cfqq has gone away, there is no | 2008 | * If the process for the cfqq has gone away, there is no |
1999 | * sense in merging the queues. | 2009 | * sense in merging the queues. |
2000 | */ | 2010 | */ |
2001 | if (process_refs == 0) | 2011 | if (process_refs == 0 || new_process_refs == 0) |
2002 | return; | 2012 | return; |
2003 | 2013 | ||
2004 | /* | 2014 | /* |
2005 | * Merge in the direction of the lesser amount of work. | 2015 | * Merge in the direction of the lesser amount of work. |
2006 | */ | 2016 | */ |
2007 | new_process_refs = cfqq_process_refs(new_cfqq); | ||
2008 | if (new_process_refs >= process_refs) { | 2017 | if (new_process_refs >= process_refs) { |
2009 | cfqq->new_cfqq = new_cfqq; | 2018 | cfqq->new_cfqq = new_cfqq; |
2010 | atomic_add(process_refs, &new_cfqq->ref); | 2019 | atomic_add(process_refs, &new_cfqq->ref); |