block/deadline-iosched.c | 120 ++++++++++++++++++++++++----------------------- 1 files changed, 63 insertions(+), 57 deletions(-) diff -puN drivers/block/deadline-iosched.c~deadline-np-42 drivers/block/deadline-iosched.c --- 25/drivers/block/deadline-iosched.c~deadline-np-42 2003-01-28 21:35:14.000000000 -0800 +++ 25-akpm/drivers/block/deadline-iosched.c 2003-01-28 21:35:14.000000000 -0800 @@ -53,15 +53,13 @@ struct deadline_data { struct rb_root sort_list[2]; struct list_head fifo_list[2]; - /* - * next in sort order. read, write or both are NULL - */ - struct deadline_rq *next_drq[2]; + struct deadline_rq *next_drq[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 */ unsigned long hash_valid_count; /* barrier hash count */ unsigned int batching; /* number of sequential requests made */ - sector_t last_sector; /* head position */ + int batch_data_dir; /* current/last batch READ or WRITE */ unsigned int starved; /* times reads have starved writes */ /* @@ -166,6 +164,27 @@ deadline_find_drq_hash(struct deadline_d #define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) #define rq_rb_key(rq) (rq)->sector +/* + * deadline_find_first_drq finds the first (lowest sector numbered) request + * for the specified data_dir. Used to sweep back to the start of the disk + * (1-way elevator) after we process the last (highest sector) request. + */ +static struct deadline_rq * +deadline_find_first_drq(struct deadline_data *dd, int data_dir) +{ + struct rb_node *n = dd->sort_list[data_dir].rb_node; + + if (n == NULL) + return NULL; + + for (;;) { + if (n->rb_left == NULL) + return rb_entry_drq(n); + + n = n->rb_left; + } +} + static struct deadline_rq * __deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) { @@ -193,7 +212,29 @@ static int deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) { struct deadline_rq *__alias; + const int data_dir = rq_data_dir(drq->request); + + /* keep the next_drq cache up to date */ + if (dd->next_drq[data_dir] != NULL) { + sector_t last = dd->last_sector[data_dir]; + sector_t next = dd->next_drq[data_dir]->request->sector; + sector_t this = drq->request->sector; + + /* + * We can have one of the following 2 situations. If "this" + * lands on a + (or L), it is a better "next" candidate. + * + * ---L+++N--- + * +++N---L+++ + */ + if ((next > last && (this >= last && this < next)) + || (next < last && (this >= last || this < next)) ) + /* we have a better "next" drq */ + dd->next_drq[data_dir] = drq; + } else + dd->next_drq[data_dir] = drq; + /* now add to the rb tree */ drq->rb_key = rq_rb_key(drq->request); __alias = __deadline_add_drq_rb(dd, drq); @@ -219,9 +260,10 @@ deadline_del_drq_rb(struct deadline_data if (dd->next_drq[data_dir] == drq) { struct rb_node *rbnext = rb_next(&drq->rb_node); - dd->next_drq[data_dir] = NULL; if (rbnext) dd->next_drq[data_dir] = rb_entry_drq(rbnext); + else + dd->next_drq[data_dir] = deadline_find_first_drq(dd, data_dir); } if (ON_RB(&drq->rb_node)) { @@ -251,24 +293,6 @@ deadline_find_drq_rb(struct deadline_dat } /* - * deadline_find_first_drq finds the first (lowest sector numbered) request - * for the specified data_dir. Used to sweep back to the start of the disk - * (1-way elevator) after we process the last (highest sector) request. - */ -static struct deadline_rq * -deadline_find_first_drq(struct deadline_data *dd, int data_dir) -{ - struct rb_node *n = dd->sort_list[data_dir].rb_node; - - for (;;) { - if (n->rb_left == NULL) - return rb_entry_drq(n); - - n = n->rb_left; - } -} - -/* * add drq to rbtree and fifo */ static inline void @@ -439,13 +463,12 @@ deadline_move_request(struct deadline_da const int data_dir = rq_data_dir(drq->request); struct rb_node *rbnext = rb_next(&drq->rb_node); - dd->next_drq[READ] = NULL; - dd->next_drq[WRITE] = NULL; - if (rbnext) dd->next_drq[data_dir] = rb_entry_drq(rbnext); - - dd->last_sector = drq->request->sector + drq->request->nr_sectors; + else + dd->next_drq[data_dir] = deadline_find_first_drq(dd, data_dir); + + dd->last_sector[data_dir] = drq->request->sector + drq->request->nr_sectors; /* * take it off the sort and fifo list, move @@ -485,20 +508,14 @@ static int deadline_dispatch_requests(st int data_dir, other_dir; /* - * batches are currently reads XOR writes + * batches are reads XOR writes */ - drq = NULL; - - if (dd->next_drq[READ]) - drq = dd->next_drq[READ]; - - if (dd->next_drq[WRITE]) - drq = dd->next_drq[WRITE]; + drq = dd->next_drq[dd->batch_data_dir]; if (drq) { /* we have a "next request" */ - if (dd->last_sector != drq->request->sector) + if (dd->last_sector[dd->batch_data_dir] != drq->request->sector) /* end the batch on a non sequential request */ dd->batching += dd->fifo_batch; @@ -511,6 +528,8 @@ static int deadline_dispatch_requests(st * at this point we are not running a batch. select the appropriate * data direction (read / write) */ + + dd->batching = 0; /* start a new batch */ if (reads) { BUG_ON(RB_EMPTY(&dd->sort_list[READ])); @@ -518,7 +537,7 @@ static int deadline_dispatch_requests(st if (writes && (dd->starved++ >= dd->writes_starved)) goto dispatch_writes; - data_dir = READ; + data_dir = dd->batch_data_dir = READ; other_dir = WRITE; goto dispatch_find_request; @@ -534,7 +553,7 @@ dispatch_writes: dd->starved = 0; - data_dir = WRITE; + data_dir = dd->batch_data_dir = WRITE; other_dir = READ; goto dispatch_find_request; @@ -546,26 +565,13 @@ dispatch_find_request: /* * we are not running a batch, find best request for selected data_dir */ - if (deadline_check_fifo(dd, data_dir)) { + if (deadline_check_fifo(dd, data_dir)) /* An expired request exists - satisfy it */ - dd->batching = 0; drq = list_entry_fifo(dd->fifo_list[data_dir].next); - - } else if (dd->next_drq[data_dir]) { - /* - * The last req was the same dir and we have a next request in - * sort order. No expired requests so continue on from here. - */ + + else + /* No expired requests, get the next in sort order */ drq = dd->next_drq[data_dir]; - } else { - /* - * The last req was the other direction or we have run out of - * higher-sectored requests. Go back to the lowest sectored - * request (1 way elevator) and start a new batch. - */ - dd->batching = 0; - drq = deadline_find_first_drq(dd, data_dir); - } dispatch_request: /* _