summaryrefslogtreecommitdiff
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:33:54 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:33:54 -0800
commit1040c54c3b98ac4f8d91bc313cdc9d6669481da3 (patch)
treed2c91b7b7e2aa5ffc88774ce1aa9aef08d4c709f /fs/buffer.c
parent5aa875d2cbee34727963bd81aa992b64480045ca (diff)
v2.4.14.8 -> v2.4.14.9
- David Brownell: usbnet update - Greg KH: USB and PCI hotplug update - Ingo/me: fix SCHED_FIFO for UP/SMP for good (flw). - Add back direct_IO now that it works again.
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index fc7638503437..e0ba7b3d077b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1172,6 +1172,7 @@ struct buffer_head * bread(kdev_t dev, int block, int size)
struct buffer_head * bh;
bh = getblk(dev, block, size);
+ touch_buffer(bh);
if (buffer_uptodate(bh))
return bh;
ll_rw_block(READ, 1, &bh);
@@ -1997,6 +1998,47 @@ int generic_block_bmap(struct address_space *mapping, long block, get_block_t *g
return tmp.b_blocknr;
}
+int generic_direct_IO(int rw, struct inode * inode, struct kiobuf * iobuf, unsigned long blocknr, int blocksize, get_block_t * get_block)
+{
+ int i, nr_blocks, retval;
+ unsigned long * blocks = iobuf->blocks;
+
+ nr_blocks = iobuf->length / blocksize;
+ /* build the blocklist */
+ for (i = 0; i < nr_blocks; i++, blocknr++) {
+ struct buffer_head bh;
+
+ bh.b_state = 0;
+ bh.b_dev = inode->i_dev;
+ bh.b_size = blocksize;
+
+ retval = get_block(inode, blocknr, &bh, rw == READ ? 0 : 1);
+ if (retval)
+ goto out;
+
+ if (rw == READ) {
+ if (buffer_new(&bh))
+ BUG();
+ if (!buffer_mapped(&bh)) {
+ /* there was an hole in the filesystem */
+ blocks[i] = -1UL;
+ continue;
+ }
+ } else {
+ if (buffer_new(&bh))
+ unmap_underlying_metadata(&bh);
+ if (!buffer_mapped(&bh))
+ BUG();
+ }
+ blocks[i] = bh.b_blocknr;
+ }
+
+ retval = brw_kiovec(rw, 1, &iobuf, inode->i_dev, iobuf->blocks, blocksize);
+
+ out:
+ return retval;
+}
+
/*
* IO completion routine for a buffer_head being used for kiobuf IO: we
* can't dispatch the kiobuf callback until io_count reaches 0.
@@ -2350,10 +2392,13 @@ static int grow_buffers(kdev_t dev, unsigned long block, int size)
unsigned long index;
int sizebits;
- if ((size & 511) || (size > PAGE_SIZE)) {
- printk(KERN_ERR "VFS: grow_buffers: size = %d\n",size);
- return 0;
- }
+ /* Size must be multiple of hard sectorsize */
+ if (size & (get_hardsect_size(dev)-1))
+ BUG();
+ /* Size must be within 512 bytes and PAGE_SIZE */
+ if (size < 512 || size > PAGE_SIZE)
+ BUG();
+
sizebits = -1;
do {
sizebits++;