lkml.org 
[lkml]   [2000]   [Aug]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: ll_rw_blk.c fails to merge requests. Help!
On Thu, Aug 24 2000, Linus Torvalds wrote:
> > Heh, but it's not that simple. The requests that are currently on
> > the pending list, are not necessarily added to the same freelist. So
> > we have to scan the pending list, and look at each request individually.
>
> Why not just have a pending list for each free list, no?

Okay, here's a new version. The pending list always contains requests
from the write list, so we can use list_splice. We batch a quarter
the size freelist, i.e. half the size of the write list -- whether
that is a good number, I don't know. I suspect it should be less
than that.

--
* Jens Axboe <axboe@suse.de>
* SuSE Labs
--- /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 {
\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.062 / U:2.160 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site