In places (ie. blk_remove_plug), we need to access the queue. Previously we would go through arq->request->q, but Hugh oopsed because I added a case which needed the queue, but we had no arq. It puts a pointer queue that "owns" the as_data in as_data. drivers/block/as-iosched.c | 41 +++++++++++++++++++---------------------- 1 files changed, 19 insertions(+), 22 deletions(-) diff -puN drivers/block/as-iosched.c~as-fix-hughs-problem drivers/block/as-iosched.c --- 25/drivers/block/as-iosched.c~as-fix-hughs-problem 2003-02-24 23:33:06.000000000 -0800 +++ 25-akpm/drivers/block/as-iosched.c 2003-02-24 23:33:10.000000000 -0800 @@ -100,13 +100,15 @@ struct as_data { * run time data */ + struct request_queue *q; /* the "owner" queue */ + /* * requests (as_rq s) are present on both sort_list and fifo_list */ struct rb_root sort_list[2]; struct list_head fifo_list[2]; - struct as_rq *next_arq[2];/* next in sort order */ + struct as_rq *next_arq[2]; /* next in sort order */ sector_t last_sector[2]; /* last READ and WRITE sectors */ struct list_head *dispatch; /* driver dispatch queue */ struct list_head *hash; /* request hash */ @@ -291,8 +293,7 @@ __as_add_arq_rb(struct as_data *ad, stru * direct IO, then move the alias to the dispatch list and then add the * request. */ -static void -as_add_arq_rb(struct as_data *ad, struct as_rq *arq) +static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq) { struct as_rq *alias; struct request *rq = arq->request; @@ -307,8 +308,7 @@ as_add_arq_rb(struct as_data *ad, struct } static struct as_rq * -as_choose_req(struct as_data *ad, - struct as_rq *arq1, struct as_rq *arq2); +as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2); static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) @@ -363,8 +363,7 @@ as_find_arq_rb(struct as_data *ad, secto /* * add arq to rbtree and fifo */ -static void -as_add_request(struct as_data *ad, struct as_rq *arq) +static void as_add_request(struct as_data *ad, struct as_rq *arq) { const int data_dir = rq_data_dir(arq->request); @@ -519,12 +518,9 @@ as_merged_requests(request_queue_t *q, s /* * move request from sort list to dispatch queue. */ -static void -as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) +static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) { - request_queue_t *q = arq->request->q; - - as_remove_request(q, arq->request); + as_remove_request(ad->q, arq->request); list_add_tail(&arq->request->queuelist, ad->dispatch); } @@ -532,14 +528,14 @@ as_move_to_dispatch(struct as_data *ad, /* * move an entry to dispatch queue */ -static void -as_move_request(struct as_data *ad, struct as_rq *arq) +static void as_move_request(struct as_data *ad, struct as_rq *arq) { const int data_dir = rq_data_dir(arq->request); BUG_ON(!ON_RB(&arq->rb_node)); - ad->last_sector[data_dir] = arq->request->sector + arq->request->nr_sectors; + ad->last_sector[data_dir] = arq->request->sector + + arq->request->nr_sectors; if (data_dir == READ) /* In case we have to anticipate after this */ @@ -825,8 +821,7 @@ static void as_update_arq(struct as_data if (ad->antic_status == ANTIC_WAIT) { del_timer(&ad->antic_timer); - if (arq) - blk_remove_plug(arq->request->q); + blk_remove_plug(ad->q); schedule_work(&ad->antic_work); } ad->antic_status = ANTIC_FINISHED; @@ -852,7 +847,7 @@ static int can_start_anticipation(struct */ del_timer(&ad->antic_timer); ad->antic_status = ANTIC_FINISHED; - blk_remove_plug(arq->request->q); + blk_remove_plug(ad->q); schedule_work(&ad->antic_work); return 0; } @@ -879,9 +874,9 @@ static int can_start_anticipation(struct * read/write expire, batch expire, etc, and moves it to the dispatch * queue. Returns 1 if a request was found, 0 otherwise. */ -static int as_dispatch_request(struct request_queue *q) +static int as_dispatch_request(struct as_data *ad) { - struct as_data *ad = q->elevator.elevator_data; + struct request_queue *q = ad->q; struct as_rq *arq; const int reads = !list_empty(&ad->fifo_list[READ]); const int writes = !list_empty(&ad->fifo_list[WRITE]); @@ -1019,7 +1014,7 @@ static struct request *as_next_request(r /* * if there are still requests on the dispatch queue, grab the first */ - if (!list_empty(ad->dispatch) || as_dispatch_request(q)) + if (!list_empty(ad->dispatch) || as_dispatch_request(ad)) rq = list_entry_rq(ad->dispatch->next); return rq; } @@ -1092,7 +1087,7 @@ static int as_queue_notready(request_que if (ad->antic_status == ANTIC_WAIT) return 1; - if (!as_dispatch_request(q)) + if (!as_dispatch_request(ad)) return 1; return 0; @@ -1170,6 +1165,8 @@ static int as_init(request_queue_t *q, e return -ENOMEM; memset(ad, 0, sizeof(*ad)); + ad->q = q; /* Identify what queue the data belongs to */ + ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL); if (!ad->hash) { kfree(ad); _