--- drivers/block/ll_rw_blk.c~ Sun Apr 16 16:47:54 2000 +++ drivers/block/ll_rw_blk.c Sun Apr 16 17:03:48 2000 @@ -242,7 +242,7 @@ static void blk_request_table_init(request_queue_t *q) { struct request *rq; - int i, lim; + int i; /* * Allocate request table for this queue @@ -310,17 +310,33 @@ * Get a free request. queue request_lock must be held and interrupts * disabled on the way in. */ -static inline struct request *get_request(request_queue_t *q, - struct list_head *list, kdev_t dev) +static inline struct request *get_request(request_queue_t *q, int rw) { + struct list_head *list = NULL; struct request *rq = NULL; - if (!list_empty(list)) { - rq = list_entry(list->next, struct request, table); + /* + * Reads get preferential treatment and are allowed to steal + * from the write free list if necessary. + */ + if (rw == READ) { + if (!list_empty(&q->request_freelist[REQUEST_LIST_READ])) { + list = &q->request_freelist[REQUEST_LIST_READ]; + rq = list_entry(list->next, struct request, table); + } + } + + if (rq == NULL) { + if (!list_empty(&q->request_freelist[REQUEST_LIST_WRITE])) { + list = &q->request_freelist[REQUEST_LIST_WRITE]; + rq = list_entry(list->next, struct request, table); + } + } + + if (rq) { list_del(&rq->table); rq->free_list = list; rq->rq_status = RQ_ACTIVE; - rq->rq_dev = dev; rq->special = NULL; rq->q = q; } @@ -331,35 +347,39 @@ /* * No available requests for this queue, unplug the device. */ -static struct request *__get_request_wait(request_queue_t *q, - struct list_head *list, kdev_t dev) +static struct request *__get_request_wait(request_queue_t *q, int rw) { + register struct request *rq; + DECLARE_WAITQUEUE(wait, current); unsigned long flags; - struct request *rq; -again: - spin_lock_irqsave(&q->request_lock, flags); - rq = get_request(q, list, dev); - spin_unlock_irqrestore(&q->request_lock, flags); - if (rq) - return rq; - - generic_unplug_device(q); - goto again; + add_wait_queue_exclusive(&q->wait_for_request, &wait); + for (;;) { + __set_current_state(TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + spin_lock_irqsave(&q->request_lock, flags); + rq = get_request(q, rw); + spin_unlock_irqrestore(&q->request_lock, flags); + if (rq) + break; + generic_unplug_device(q); + schedule(); + } + remove_wait_queue(&q->wait_for_request, &wait); + current->state = TASK_RUNNING; + return rq; } -static inline struct request *get_request_wait(request_queue_t *q, - struct list_head *list, kdev_t dev) +static inline struct request *get_request_wait(request_queue_t *q, int rw) { - register struct request *req; + register struct request *rq; unsigned long flags; spin_lock_irqsave(&q->request_lock, flags); - req = get_request(q, list, dev); + rq = get_request(q, rw); spin_unlock_irqrestore(&q->request_lock, flags); - if (req) - return req; - return __get_request_wait(q, list, dev); + if (rq) + return rq; + return __get_request_wait(q, rw); } /* RO fail safe mechanism */ @@ -753,26 +773,14 @@ * are not crucial. */ get_rq: - req = NULL; - if (rw == READ) - req = get_request(q, &q->request_freelist[REQUEST_LIST_READ], bh->b_rdev); - - if (req == NULL) - req = get_request(q, &q->request_freelist[REQUEST_LIST_WRITE], bh->b_rdev); + req = get_request(q, rw); if (req == NULL) { - struct list_head *list; - spin_unlock_irqrestore(&q->request_lock, flags); if (rw_ahead) goto end_io; - if (rw == READ) - list = &q->request_freelist[REQUEST_LIST_READ]; - else - list = &q->request_freelist[REQUEST_LIST_WRITE]; - - req = __get_request_wait(q, list, bh->b_rdev); + req = __get_request_wait(q, rw); spin_lock_irqsave(&q->request_lock, flags); /* @@ -795,6 +803,7 @@ req->sem = NULL; req->bh = bh; req->bhtail = bh; + req->rq_dev = bh->b_rdev; add_request(q, req, head, orig_latency); elevator_account_request(elevator, req); --- fs/buffer.c~ Sun Apr 16 16:47:54 2000 +++ fs/buffer.c Sun Apr 16 16:05:04 2000 @@ -149,9 +149,9 @@ add_wait_queue(&bh->b_wait, &wait); do { generic_unplug_device((request_queue_t *)bh->b_queue); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!buffer_locked(bh)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE); schedule(); } while (buffer_locked(bh)); tsk->state = TASK_RUNNING;