===== drivers/block/ll_rw_blk.c 1.47 vs edited ===== --- 1.47/drivers/block/ll_rw_blk.c Fri Jul 11 04:30:54 2003 +++ edited/drivers/block/ll_rw_blk.c Wed Jul 16 12:27:24 2003 @@ -458,6 +458,7 @@ INIT_LIST_HEAD(&q->rq.free); q->rq.count = 0; + q->rq.pending[READ] = q->rq.pending[WRITE] = 0; q->nr_requests = 0; si_meminfo(&si); @@ -549,18 +550,35 @@ static struct request *get_request(request_queue_t *q, int rw) { struct request *rq = NULL; - struct request_list *rl; + struct request_list *rl = &q->rq; - rl = &q->rq; - if (!list_empty(&rl->free) && !blk_oversized_queue(q)) { + if (blk_oversized_queue(q)) { + int rlim = q->nr_requests >> 5; + + if (rlim < 4) + rlim = 4; + + /* + * if its a write, or we have more than a handful of reads + * pending, bail out + */ + if ((rw == WRITE) || (rw == READ && rl->pending[READ] > rlim)) + return NULL; + if (blk_oversized_queue_reads(q)) + return NULL; + } + + if (!list_empty(&rl->free)) { rq = blkdev_free_rq(&rl->free); list_del(&rq->queue); rl->count--; + rl->pending[rw]++; rq->rq_status = RQ_ACTIVE; rq->cmd = rw; rq->special = NULL; rq->q = q; } + return rq; } @@ -866,13 +884,25 @@ * assume it has free buffers and check waiters */ if (q) { + struct request_list *rl = &q->rq; int oversized_batch = 0; if (q->can_throttle) oversized_batch = blk_oversized_queue_batch(q); - q->rq.count++; - list_add(&req->queue, &q->rq.free); - if (q->rq.count >= q->batch_requests && !oversized_batch) { + rl->count++; + /* + * paranoia check + */ + if (req->cmd == READ || req->cmd == WRITE) + rl->pending[req->cmd]--; + if (rl->pending[READ] > q->nr_requests) + printk("reads: %u\n", rl->pending[READ]); + if (rl->pending[WRITE] > q->nr_requests) + printk("writes: %u\n", rl->pending[WRITE]); + if (rl->pending[READ] + rl->pending[WRITE] > q->nr_requests) + printk("too many: %u + %u > %u\n", rl->pending[READ], rl->pending[WRITE], q->nr_requests); + list_add(&req->queue, &rl->free); + if (rl->count >= q->batch_requests && !oversized_batch) { smp_mb(); if (waitqueue_active(&q->wait_for_requests)) wake_up(&q->wait_for_requests); @@ -947,7 +977,7 @@ static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh) { - unsigned int sector, count; + unsigned int sector, count, sync; int max_segments = MAX_SEGMENTS; struct request * req, *freereq = NULL; int rw_ahead, max_sectors, el_ret; @@ -958,6 +988,7 @@ count = bh->b_size >> 9; sector = bh->b_rsector; + sync = test_and_clear_bit(BH_Sync, &bh->b_state); rw_ahead = 0; /* normal case; gets changed below for READA */ switch (rw) { @@ -1124,6 +1155,8 @@ blkdev_release_request(freereq); if (should_wake) get_request_wait_wakeup(q, rw); + if (sync) + __generic_unplug_device(q); spin_unlock_irq(&io_request_lock); return 0; end_io: ===== fs/buffer.c 1.89 vs edited ===== --- 1.89/fs/buffer.c Tue Jun 24 17:11:29 2003 +++ edited/fs/buffer.c Tue Jul 15 15:31:07 2003 @@ -1142,6 +1142,7 @@ bh = getblk(dev, block, size); if (buffer_uptodate(bh)) return bh; + set_bit(BH_Sync, &bh->b_state); ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) ===== include/linux/blkdev.h 1.24 vs edited ===== --- 1.24/include/linux/blkdev.h Fri Jul 4 13:18:12 2003 +++ edited/include/linux/blkdev.h Tue Jul 15 16:32:32 2003 @@ -66,6 +66,7 @@ struct request_list { unsigned int count; + unsigned int pending[2]; struct list_head free; }; @@ -292,6 +293,13 @@ { if (q->can_throttle) return atomic_read(&q->nr_sectors) > q->max_queue_sectors; + return q->rq.count == 0; +} + +static inline int blk_oversized_queue_reads(request_queue_t * q) +{ + if (q->can_throttle) + return atomic_read(&q->nr_sectors) > q->max_queue_sectors + q->batch_sectors; return q->rq.count == 0; } ===== include/linux/fs.h 1.82 vs edited ===== --- 1.82/include/linux/fs.h Wed Jul 9 14:42:38 2003 +++ edited/include/linux/fs.h Tue Jul 15 15:31:07 2003 @@ -221,6 +221,7 @@ BH_Launder, /* 1 if we can throttle on this buffer */ BH_Attached, /* 1 if b_inode_buffers is linked into a list */ BH_JBD, /* 1 if it has an attached journal_head */ + BH_Sync, /* 1 if the buffer is a sync read */ BH_PrivateStart,/* not a state bit, but the first bit available * for private allocation by other entities