patch-2.1.63 linux/drivers/block/ll_rw_blk.c
Next file: linux/drivers/block/md.c
Previous file: linux/drivers/block/linear.c
Back to the patch index
Back to the overall index
- Lines: 172
- Date:
Sat Nov 8 11:39:12 1997
- Orig file:
v2.1.62/linux/drivers/block/ll_rw_blk.c
- Orig date:
Mon Aug 18 18:19:45 1997
diff -u --recursive --new-file v2.1.62/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
@@ -82,6 +82,11 @@
*/
int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
+/*
+ * The following tunes the read-ahead algorithm in mm/filemap.c
+ */
+int * max_readahead[MAX_BLKDEV] = { NULL, NULL, };
+
static inline struct request **get_queue(kdev_t dev)
{
int major = MAJOR(dev);
@@ -295,7 +300,27 @@
sti();
}
-static void make_request(int major,int rw, struct buffer_head * bh)
+#define MAX_SECTORS 244
+
+static inline void attempt_merge (struct request *req)
+{
+ struct request *next = req->next;
+
+ if (!next)
+ return;
+ if (req->sector + req->nr_sectors != next->sector)
+ return;
+ if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors >= MAX_SECTORS)
+ return;
+ req->bhtail->b_reqnext = next->bh;
+ req->bhtail = next->bhtail;
+ req->nr_sectors += next->nr_sectors;
+ next->rq_status = RQ_INACTIVE;
+ req->next = next->next;
+ wake_up (&wait_for_request);
+}
+
+void make_request(int major,int rw, struct buffer_head * bh)
{
unsigned int sector, count;
struct request * req;
@@ -313,7 +338,7 @@
if (blk_size[major])
if (blk_size[major][MINOR(bh->b_rdev)] < (sector + count)>>1) {
- bh->b_state &= (1 << BH_Lock) | (1 << BH_FreeOnIO);
+ bh->b_state &= (1 << BH_Lock);
/* This may well happen - the kernel calls bread()
without checking the size of the device, e.g.,
when mounting a device. */
@@ -323,8 +348,7 @@
kdevname(bh->b_rdev), rw,
(sector + count)>>1,
blk_size[major][MINOR(bh->b_rdev)]);
- unlock_buffer(bh);
- return;
+ goto end_io;
}
rw_ahead = 0; /* normal case; gets changed below for READA/WRITEA */
@@ -333,10 +357,8 @@
rw_ahead = 1;
rw = READ; /* drop into READ */
case READ:
- if (buffer_uptodate(bh)) {
- unlock_buffer(bh); /* Hmmph! Already have it */
- return;
- }
+ if (buffer_uptodate(bh)) /* Hmmph! Already have it */
+ goto end_io;
kstat.pgpgin++;
max_req = NR_REQUEST; /* reads take precedence */
break;
@@ -344,10 +366,8 @@
rw_ahead = 1;
rw = WRITE; /* drop into WRITE */
case WRITE:
- if (!buffer_dirty(bh)) {
- unlock_buffer(bh); /* Hmmph! Nothing to write */
- return;
- }
+ if (!buffer_dirty(bh)) /* Hmmph! Nothing to write */
+ goto end_io;
/* We don't allow the write-requests to fill up the
* queue completely: we want some room for reads,
* as they take precedence. The last third of the
@@ -359,8 +379,7 @@
default:
printk(KERN_ERR "make_request: bad block dev cmd,"
" must be R/W/RA/WA\n");
- unlock_buffer(bh);
- return;
+ goto end_io;
}
/* look for a free request. */
@@ -409,7 +428,7 @@
continue;
if (req->cmd != rw)
continue;
- if (req->nr_sectors >= 244)
+ if (req->nr_sectors >= MAX_SECTORS)
continue;
if (req->rq_dev != bh->b_rdev)
continue;
@@ -417,6 +436,9 @@
if (req->sector + req->nr_sectors == sector) {
req->bhtail->b_reqnext = bh;
req->bhtail = bh;
+ req->nr_sectors += count;
+ /* Can we now merge this req with the next? */
+ attempt_merge(req);
/* or to the beginning? */
} else if (req->sector - count == sector) {
bh->b_reqnext = req->bh;
@@ -424,10 +446,10 @@
req->buffer = bh->b_data;
req->current_nr_sectors = count;
req->sector = sector;
+ req->nr_sectors += count;
} else
continue;
- req->nr_sectors += count;
mark_buffer_clean(bh);
sti();
return;
@@ -440,10 +462,8 @@
/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
if (!req) {
- if (rw_ahead) {
- unlock_buffer(bh);
- return;
- }
+ if (rw_ahead)
+ goto end_io;
req = __get_request_wait(max_req, bh->b_rdev);
}
@@ -459,6 +479,10 @@
req->bhtail = bh;
req->next = NULL;
add_request(major+blk_dev,req);
+ return;
+
+end_io:
+ bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
}
/* This function can be used to request a number of buffers from a block
@@ -530,6 +554,12 @@
for (i = 0; i < nr; i++) {
if (bh[i]) {
set_bit(BH_Req, &bh[i]->b_state);
+#ifdef CONFIG_BLK_DEV_MD
+ if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
+ md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
+ continue;
+ }
+#endif
make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
}
}
@@ -654,6 +684,7 @@
req->next = NULL;
}
memset(ro_bits,0,sizeof(ro_bits));
+ memset(max_readahead, 0, sizeof(max_readahead));
#ifdef CONFIG_AMIGA_Z2RAM
z2_init();
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov