--- /opt/kernel/linux-2.4.0-test7/drivers/block/ll_rw_blk.c Thu Aug 24 05:12:54 2000 +++ drivers/block/ll_rw_blk.c Thu Aug 24 23:49:25 2000 @@ -423,6 +423,7 @@ INIT_LIST_HEAD(&q->queue_head); INIT_LIST_HEAD(&q->request_freelist[READ]); INIT_LIST_HEAD(&q->request_freelist[WRITE]); + INIT_LIST_HEAD(&q->pending_freelist); elevator_init(&q->elevator, ELEVATOR_LINUS); blk_init_free_list(q); q->request_fn = rfn; @@ -442,6 +443,7 @@ */ q->plug_device_fn = generic_plug_device; q->head_active = 1; + q->pending_free = 0; } @@ -494,9 +496,9 @@ register struct request *rq; DECLARE_WAITQUEUE(wait, current); - add_wait_queue_exclusive(&q->wait_for_request, &wait); + add_wait_queue(&q->wait_for_request, &wait); for (;;) { - __set_current_state(TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + __set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_irq(&io_request_lock); rq = get_request(q, rw); spin_unlock_irq(&io_request_lock); @@ -609,16 +611,46 @@ */ void inline blkdev_release_request(struct request *req) { + request_queue_t *q = req->q; + struct list_head *write_list = &q->request_freelist[WRITE]; + req->rq_status = RQ_INACTIVE; /* * Request may not have originated from ll_rw_blk */ - if (req->free_list) { - list_add(&req->table, req->free_list); - req->free_list = NULL; - wake_up(&req->q->wait_for_request); + if (req->free_list == NULL) + return; + + /* + * no one waiting for free requests + */ + if (!waitqueue_active(&q->wait_for_request)) { + if (!list_empty(&q->pending_freelist)) { + list_splice(&q->pending_freelist, write_list); + INIT_LIST_HEAD(&q->pending_freelist); + } + goto add; } + + if (req->free_list == &q->request_freelist[READ]) + goto add; + + /* + * batch request freeing + */ + list_add(&req->table, &q->pending_freelist); + if (++q->pending_free > (QUEUE_NR_REQUESTS >> 2)) { + list_splice(&q->pending_freelist, write_list); + INIT_LIST_HEAD(&q->pending_freelist); + q->pending_free = 0; + wake_up(&q->wait_for_request); + } + return; + +add: + list_add(&req->table, req->free_list); + req->free_list = NULL; } /* --- /opt/kernel/linux-2.4.0-test7/include/linux/blkdev.h Thu Aug 10 14:28:06 2000 +++ include/linux/blkdev.h Thu Aug 24 23:24:59 2000 @@ -77,7 +77,7 @@ * the queue request freelist, one for reads and one for writes */ struct list_head request_freelist[2]; - + struct list_head pending_freelist; /* * Together with queue_head for cacheline sharing */ @@ -122,6 +122,11 @@ * Tasks wait here for free request */ wait_queue_head_t wait_for_request; + + /* + * for batch-freeing of released requests + */ + int pending_free; }; struct blk_dev_struct {