Commit 1140b22f authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] CFQ: allocation under lock, missing memset on allocation

This fixes two issues in the CFQ IO-scheduler:

o Still a bad allocation under the queue lock
o We need to clear crq after mempool_alloc(), otherwise the rbtree
  pointers can contain garbage if slab poisoning is enabled. This causes
  crashes on front/back merges because rb_next() returns crap.
Signed-off-by: default avatarJens Axboe <axboe@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 29b6d1fb
...@@ -460,12 +460,24 @@ static struct cfq_queue *__cfq_get_queue(struct cfq_data *cfqd, int pid, ...@@ -460,12 +460,24 @@ static struct cfq_queue *__cfq_get_queue(struct cfq_data *cfqd, int pid,
int gfp_mask) int gfp_mask)
{ {
const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT); const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT);
struct cfq_queue *cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval); struct cfq_queue *cfqq, *new_cfqq = NULL;
request_queue_t *q = cfqd->queue;
retry:
cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval);
if (!cfqq) { if (!cfqq) {
cfqq = mempool_alloc(cfq_mpool, gfp_mask); if (new_cfqq) {
cfqq = new_cfqq;
new_cfqq = NULL;
} else if (gfp_mask & __GFP_WAIT) {
spin_unlock_irq(q->queue_lock);
new_cfqq = mempool_alloc(cfq_mpool, gfp_mask);
spin_lock_irq(q->queue_lock);
goto retry;
} else
return NULL;
if (cfqq) {
INIT_LIST_HEAD(&cfqq->cfq_hash); INIT_LIST_HEAD(&cfqq->cfq_hash);
INIT_LIST_HEAD(&cfqq->cfq_list); INIT_LIST_HEAD(&cfqq->cfq_list);
RB_CLEAR_ROOT(&cfqq->sort_list); RB_CLEAR_ROOT(&cfqq->sort_list);
...@@ -474,7 +486,9 @@ static struct cfq_queue *__cfq_get_queue(struct cfq_data *cfqd, int pid, ...@@ -474,7 +486,9 @@ static struct cfq_queue *__cfq_get_queue(struct cfq_data *cfqd, int pid,
cfqq->queued[0] = cfqq->queued[1] = 0; cfqq->queued[0] = cfqq->queued[1] = 0;
list_add(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); list_add(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
} }
}
if (new_cfqq)
mempool_free(new_cfqq, cfq_mpool);
return cfqq; return cfqq;
} }
...@@ -653,6 +667,7 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) ...@@ -653,6 +667,7 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
crq = mempool_alloc(cfqd->crq_pool, gfp_mask); crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
if (crq) { if (crq) {
memset(crq, 0, sizeof(*crq));
RB_CLEAR(&crq->rb_node); RB_CLEAR(&crq->rb_node);
crq->request = rq; crq->request = rq;
crq->cfq_queue = NULL; crq->cfq_queue = NULL;
......
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