Re: [patch] pagecache-2.3.9-H3, bmap & ext2fs cleanup patch

Andrea Arcangeli (andrea@suse.de)
Sun, 27 Jun 1999 16:23:56 +0200 (CEST)


On Sun, 27 Jun 1999, Ingo Molnar wrote:

>make_request() handles it already. Am i overlooking something?

Yes, ll_rw_block suppose that all buffer passed in the array blongs to the
same blockdevice. I noticed this getting bug-reports from people using my
early 2.2.x-VM patches :). I couldn't notice this since I have everything
on the same blockdevice. My current ll_rw_block looks like this (and it's
multi-blockdevice capable).

(patch against pre-2.3.9-4)

Index: ll_rw_blk.c
===================================================================
RCS file: /var/cvs/linux/drivers/block/ll_rw_blk.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 ll_rw_blk.c
--- ll_rw_blk.c 1999/06/26 02:45:33 1.1.1.11
+++ ll_rw_blk.c 1999/06/27 14:20:51
@@ -206,7 +206,7 @@
/*
* wait until a free request in the first N entries is available.
*/
-static struct request * __get_request_wait(int n, kdev_t dev)
+static inline struct request * get_request_wait(int n, kdev_t dev)
{
register struct request *req;
DECLARE_WAITQUEUE(wait, current);
@@ -214,33 +214,25 @@

add_wait_queue(&wait_for_request, &wait);
for (;;) {
+ run_task_queue(&tq_disk);
current->state = TASK_UNINTERRUPTIBLE;
spin_lock_irqsave(&io_request_lock,flags);
req = get_request(n, dev);
spin_unlock_irqrestore(&io_request_lock,flags);
if (req)
break;
- run_task_queue(&tq_disk);
schedule();
+ spin_lock_irqsave(&io_request_lock,flags);
+ req = get_request(n, dev);
+ spin_unlock_irqrestore(&io_request_lock,flags);
+ if (req)
+ break;
}
remove_wait_queue(&wait_for_request, &wait);
current->state = TASK_RUNNING;
return req;
}

-static inline struct request * get_request_wait(int n, kdev_t dev)
-{
- register struct request *req;
- unsigned long flags;
-
- spin_lock_irqsave(&io_request_lock,flags);
- req = get_request(n, dev);
- spin_unlock_irqrestore(&io_request_lock,flags);
- if (req)
- return req;
- return __get_request_wait(n, dev);
-}
-
/* RO fail safe mechanism */

static long ro_bits[MAX_BLKDEV][8];
@@ -542,8 +535,8 @@
/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
if (!req) {
if (rw_ahead)
- goto end_io;
- req = __get_request_wait(max_req, bh->b_rdev);
+ goto failed_ahead;
+ req = get_request_wait(max_req, bh->b_rdev);
}

/* fill up the request-info, and add it to the queue */
@@ -560,6 +553,16 @@
add_request(major+blk_dev,req);
return;

+failed_ahead:
+ switch (rw)
+ {
+ case READ:
+ kstat.pgpgin--;
+ break;
+ case WRITE:
+ kstat.pgpgout--;
+ break;
+ }
end_io:
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
}
@@ -570,9 +573,6 @@

void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
{
- unsigned int major;
- int correct_size;
- struct blk_dev_struct * dev;
int i;

/* Make sure that the first block contains something reasonable */
@@ -582,30 +582,36 @@
return;
}

- dev = NULL;
- if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV)
- dev = blk_dev + major;
- if (!dev || !dev->request_fn) {
- printk(KERN_ERR
- "ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n",
- kdevname(bh[0]->b_dev), bh[0]->b_blocknr);
- goto sorry;
- }
-
- /* Determine correct block size for this device. */
- correct_size = BLOCK_SIZE;
- if (blksize_size[major]) {
- i = blksize_size[major][MINOR(bh[0]->b_dev)];
- if (i)
- correct_size = i;
- }
+ for (i = 0; i < nr; i++)
+ {
+ unsigned int major;
+ int correct_size;
+ struct blk_dev_struct * dev;
+
+ dev = NULL;
+ if ((major = MAJOR(bh[i]->b_dev)) < MAX_BLKDEV)
+ dev = blk_dev + major;
+ if (!dev || !dev->request_fn) {
+ printk(KERN_ERR
+ "ll_rw_block: Trying to read nonexistent "
+ "block-device %s (%ld)\n",
+ kdevname(bh[i]->b_dev), bh[i]->b_blocknr);
+ goto sorry;
+ }

- /* Verify requested block sizes. */
- for (i = 0; i < nr; i++) {
+ /* Determine correct block size for this device. */
+ correct_size = BLOCK_SIZE;
+ if (blksize_size[major]) {
+ int tmp_size;
+ tmp_size = blksize_size[major][MINOR(bh[i]->b_dev)];
+ if (tmp_size)
+ correct_size = tmp_size;
+ }
+ /* Verify requested block sizes. */
if (bh[i]->b_size != correct_size) {
printk(KERN_NOTICE "ll_rw_block: device %s: "
"only %d-char blocks implemented (%lu)\n",
- kdevname(bh[0]->b_dev),
+ kdevname(bh[i]->b_dev),
correct_size, bh[i]->b_size);
goto sorry;
}
@@ -622,35 +628,31 @@
goto sorry;
}
#endif
- }
-
- if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) {
- printk(KERN_NOTICE "Can't write to read-only device %s\n",
- kdevname(bh[0]->b_dev));
- goto sorry;
+ if ((rw == WRITE || rw == WRITEA) &&
+ is_read_only(bh[i]->b_dev)) {
+ printk(KERN_NOTICE
+ "Can't write to read-only device %s\n",
+ kdevname(bh[i]->b_dev));
+ goto sorry;
+ }
}

for (i = 0; i < nr; i++) {
- if (bh[i]) {
- set_bit(BH_Req, &bh[i]->b_state);
+ 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;
- }
+ if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
+ md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
+ } else
#endif
make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
- }
}
return;

sorry:
for (i = 0; i < nr; i++) {
- if (bh[i]) {
- clear_bit(BH_Dirty, &bh[i]->b_state);
- clear_bit(BH_Uptodate, &bh[i]->b_state);
- bh[i]->b_end_io(bh[i], 0);
- }
+ clear_bit(BH_Dirty, &bh[i]->b_state);
+ clear_bit(BH_Uptodate, &bh[i]->b_state);
+ bh[i]->b_end_io(bh[i], 0);
}
return;
}

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/