Commit 21301d43 authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] cfq-iosched: exit deadlock

CFQ v2 has some spare queue logic that was never enabled.  It has an SMP
deadlock because it attempts to regrab the queue lock in the exit path, so
kill the spare queue stuff completely for 2.6.10.
Signed-off-by: default avatarJens Axboe <axboe@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 002984e2
...@@ -93,11 +93,6 @@ enum { ...@@ -93,11 +93,6 @@ enum {
static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL }; static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL };
/*
* spare queue
*/
#define CFQ_KEY_SPARE (~0UL)
static kmem_cache_t *crq_pool; static kmem_cache_t *crq_pool;
static kmem_cache_t *cfq_pool; static kmem_cache_t *cfq_pool;
static kmem_cache_t *cfq_ioc_pool; static kmem_cache_t *cfq_ioc_pool;
...@@ -1234,19 +1229,6 @@ __cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask) ...@@ -1234,19 +1229,6 @@ __cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask)
return cfqq; return cfqq;
} }
static struct cfq_queue *
cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask)
{
request_queue_t *q = cfqd->queue;
struct cfq_queue *cfqq;
spin_lock_irq(q->queue_lock);
cfqq = __cfq_get_queue(cfqd, key, gfp_mask);
spin_unlock_irq(q->queue_lock);
return cfqq;
}
static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq) static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq)
{ {
crq->is_sync = 0; crq->is_sync = 0;
...@@ -1433,14 +1415,8 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) ...@@ -1433,14 +1415,8 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
spin_lock_irqsave(q->queue_lock, flags); spin_lock_irqsave(q->queue_lock, flags);
cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask); cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask);
if (!cfqq) { if (!cfqq)
#if 0
cfqq = cfq_get_queue(cfqd, CFQ_KEY_SPARE, gfp_mask);
printk("%s: got spare queue\n", current->comm);
#else
goto out_lock; goto out_lock;
#endif
}
repeat: repeat:
if (cfqq->allocated[rw] >= cfqd->max_queued) if (cfqq->allocated[rw] >= cfqd->max_queued)
...@@ -1495,21 +1471,10 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) ...@@ -1495,21 +1471,10 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
static void cfq_put_cfqd(struct cfq_data *cfqd) static void cfq_put_cfqd(struct cfq_data *cfqd)
{ {
request_queue_t *q = cfqd->queue; request_queue_t *q = cfqd->queue;
struct cfq_queue *cfqq;
if (!atomic_dec_and_test(&cfqd->ref)) if (!atomic_dec_and_test(&cfqd->ref))
return; return;
/*
* kill spare queue, getting it means we have two refences to it.
* drop both
*/
spin_lock_irq(q->queue_lock);
cfqq = __cfq_get_queue(cfqd, CFQ_KEY_SPARE, GFP_ATOMIC);
cfq_put_queue(cfqq);
cfq_put_queue(cfqq);
spin_unlock_irq(q->queue_lock);
blk_put_queue(q); blk_put_queue(q);
mempool_destroy(cfqd->crq_pool); mempool_destroy(cfqd->crq_pool);
...@@ -1526,7 +1491,6 @@ static void cfq_exit_queue(elevator_t *e) ...@@ -1526,7 +1491,6 @@ static void cfq_exit_queue(elevator_t *e)
static int cfq_init_queue(request_queue_t *q, elevator_t *e) static int cfq_init_queue(request_queue_t *q, elevator_t *e)
{ {
struct cfq_data *cfqd; struct cfq_data *cfqd;
struct cfq_queue *cfqq;
int i; int i;
cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL); cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
...@@ -1559,13 +1523,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) ...@@ -1559,13 +1523,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
cfqd->queue = q; cfqd->queue = q;
atomic_inc(&q->refcnt); atomic_inc(&q->refcnt);
/*
* setup spare failure queue
*/
cfqq = cfq_get_queue(cfqd, CFQ_KEY_SPARE, GFP_KERNEL);
if (!cfqq)
goto out_spare;
/* /*
* 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
* some requests. fairness is handled differently * some requests. fairness is handled differently
...@@ -1586,8 +1543,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) ...@@ -1586,8 +1543,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
cfqd->cfq_back_penalty = cfq_back_penalty; cfqd->cfq_back_penalty = cfq_back_penalty;
return 0; return 0;
out_spare:
mempool_destroy(cfqd->crq_pool);
out_crqpool: out_crqpool:
kfree(cfqd->cfq_hash); kfree(cfqd->cfq_hash);
out_cfqhash: out_cfqhash:
......
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