Index: linux-2.6.7-ck/drivers/block/cfq-iosched.c =================================================================== --- linux-2.6.7-ck.orig/drivers/block/cfq-iosched.c 2004-05-23 12:54:49.000000000 +1000 +++ linux-2.6.7-ck/drivers/block/cfq-iosched.c 2004-07-07 22:45:07.667812361 +1000 @@ -445,21 +445,23 @@ mempool_free(cfqq, cfq_mpool); } -static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, int pid) +static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, int pid, int mask) { const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT); struct cfq_queue *cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval); if (!cfqq) { - cfqq = mempool_alloc(cfq_mpool, GFP_NOIO); + cfqq = mempool_alloc(cfq_mpool, mask); - 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 (cfqq) { + 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]); + } } return cfqq; @@ -467,15 +469,22 @@ static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq) { - struct cfq_queue *cfqq; - - cfqq = cfq_get_queue(cfqd, current->tgid); + struct cfq_queue *cfqq = cfq_get_queue(cfqd, current->tgid, GFP_ATOMIC); - cfq_add_crq_rb(cfqd, cfqq, crq); + if (cfqq) { + cfq_add_crq_rb(cfqd, cfqq, crq); - if (list_empty(&cfqq->cfq_list)) { - list_add(&cfqq->cfq_list, &cfqd->rr_list); - cfqd->busy_queues++; + if (list_empty(&cfqq->cfq_list)) { + list_add(&cfqq->cfq_list, &cfqd->rr_list); + cfqd->busy_queues++; + } + } else { + /* + * should can only happen if the request wasn't allocated + * through blk_alloc_request(), eg stack requests from ide-cd + * (those should be removed) _and_ we are in OOM. + */ + list_add_tail(&crq->request->queuelist, cfqd->dispatch); } } @@ -587,8 +596,17 @@ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { struct cfq_data *cfqd = q->elevator.elevator_data; - struct cfq_rq *crq = mempool_alloc(cfqd->crq_pool, gfp_mask); + struct cfq_queue *cfqq; + struct cfq_rq *crq; + + /* + * prepare a queue up front, so cfq_enqueue() doesn't have to + */ + cfqq = cfq_get_queue(cfqd, current->tgid, gfp_mask); + if (!cfqq) + return 1; + crq = mempool_alloc(cfqd->crq_pool, gfp_mask); if (crq) { RB_CLEAR(&crq->rb_node); crq->request = rq;