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,22 +460,36 @@ static struct cfq_queue *__cfq_get_queue(struct cfq_data *cfqd, int pid, ...@@ -460,22 +460,36 @@ 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;
if (!cfqq) {
cfqq = mempool_alloc(cfq_mpool, gfp_mask);
if (cfqq) { retry:
INIT_LIST_HEAD(&cfqq->cfq_hash); cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval);
INIT_LIST_HEAD(&cfqq->cfq_list);
RB_CLEAR_ROOT(&cfqq->sort_list);
cfqq->pid = pid; if (!cfqq) {
cfqq->queued[0] = cfqq->queued[1] = 0; if (new_cfqq) {
list_add(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); 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;
INIT_LIST_HEAD(&cfqq->cfq_hash);
INIT_LIST_HEAD(&cfqq->cfq_list);
RB_CLEAR_ROOT(&cfqq->sort_list);
cfqq->pid = pid;
cfqq->queued[0] = cfqq->queued[1] = 0;
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