--- xfstest/linux/include/linux/elevator.h Wed Feb 14 16:55:55 2001 +++ 2.4xfs-pure/linux/include/linux/elevator.h Tue Feb 6 19:32:56 2001 @@ -8,7 +8,8 @@ struct list_head *, int); typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct list_head *, - struct buffer_head *, int, int, int); + struct buffer_head *, int, int, int, struct kiobuf *, + kdev_t, unsigned int); typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int); @@ -26,11 +27,11 @@ unsigned int queue_ID; }; -int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int); +int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int, struct kiobuf *, kdev_t, unsigned int); void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int); void elevator_noop_merge_req(struct request *, struct request *); -int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int); +int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int, struct kiobuf *, kdev_t, unsigned int); void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int); void elevator_linus_merge_req(struct request *, struct request *); --- xfstest/linux/drivers/block/elevator.c Wed Feb 14 16:54:14 2001 +++ 2.4xfs-pure/linux/drivers/block/elevator.c Tue Feb 6 19:32:14 2001 @@ -30,11 +30,17 @@ int elevator_linus_merge(request_queue_t *q, struct request **req, struct list_head * head, struct buffer_head *bh, int rw, - int max_sectors, int max_segments) + int max_sectors, int max_segments, + struct kiobuf * kiobuf, kdev_t dev, + unsigned int kendsector) { struct list_head *entry = &q->queue_head; - unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE; + unsigned int count, ret = ELEVATOR_NO_MERGE; + unsigned int tmpdist, currdist = INT_MAX; + if (bh) + count = bh->b_size >> 9; + while ((entry = entry->prev) != head) { struct request *__rq = blkdev_entry_to_request(entry); @@ -45,32 +51,38 @@ *req = __rq; break; } - - if (__rq->kiobuf) - continue; - if (__rq->sem) - continue; - if (__rq->cmd != rw) - continue; - if (__rq->rq_dev != bh->b_rdev) - continue; - if (__rq->nr_sectors + count > max_sectors) - continue; - if (__rq->elevator_sequence < count) - break; - if (__rq->sector + __rq->nr_sectors == bh->b_rsector) { - ret = ELEVATOR_BACK_MERGE; - *req = __rq; - break; - } else if (__rq->sector - count == bh->b_rsector) { - ret = ELEVATOR_FRONT_MERGE; - __rq->elevator_sequence -= count; - *req = __rq; - break; - } else if (!*req && BHRQ_IN_ORDER(bh, __rq)) - *req = __rq; - } - + if (bh) { + if (__rq->sem) + continue; + if (__rq->cmd != rw) + continue; + if (__rq->rq_dev != bh->b_rdev) + continue; + if (__rq->nr_sectors + count > max_sectors) + continue; + if (__rq->elevator_sequence < count) + break; + if (__rq->bh && __rq->sector + __rq->nr_sectors == bh->b_rsector) { + ret = ELEVATOR_BACK_MERGE; + *req = __rq; + break; + } else if (__rq->bh && __rq->sector - count == bh->b_rsector) { + ret = ELEVATOR_FRONT_MERGE; + __rq->elevator_sequence -= count; + *req = __rq; + break; + } else if (!*req && BHRQ_IN_ORDER(bh, __rq)) { + *req = __rq; + } + } else if (dev == __rq->rq_dev && kendsector < __rq->sector) { + tmpdist = __rq->sector - kendsector; + if (tmpdist < currdist) { + *req = __rq; + currdist = tmpdist; + } + } + } + return ret; } @@ -99,7 +111,9 @@ int elevator_noop_merge(request_queue_t *q, struct request **req, struct list_head * head, struct buffer_head *bh, int rw, - int max_sectors, int max_segments) + int max_sectors, int max_segments, + struct kiobuf * kiobuf, kdev_t dev, + unsigned int kendsector) { struct list_head *entry; unsigned int count = bh->b_size >> 9; --- xfstest/linux/drivers/block/ll_rw_blk.c Wed Feb 14 16:54:14 2001 +++ 2.4xfs-pure/linux/drivers/block/ll_rw_blk.c Wed Feb 7 16:31:20 2001 @@ -952,11 +952,9 @@ } else if (q->head_active && !q->plugged) head = head->next; - if (kiobuf) - goto get_rq; - el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw, - max_sectors, max_segments); + max_sectors, max_segments, + kiobuf, dev, sector+count); switch (el_ret) { case ELEVATOR_BACK_MERGE: @@ -1401,14 +1399,24 @@ goto end_io; } + /* + * don't initiate I/O if we're already above the high + * water mark. instead start I/O on the queued stuff. + */ + if (atomic_read(&queued_sectors) >= high_queued_sectors) { + run_task_queue(&tq_disk); + wait_event(blk_buffers_wait, + atomic_read(&queued_sectors) < low_queued_sectors); + } + switch(rw) { case WRITE: - kstat.pgpgout++; + kstat.pgpgout += (kiobuf->length >> 9); break; case READA: case READ: - kstat.pgpgin++; + kstat.pgpgin += (kiobuf->length >> 9); break; default: BUG();