diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:33:54 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:33:54 -0800 |
| commit | 1040c54c3b98ac4f8d91bc313cdc9d6669481da3 (patch) | |
| tree | d2c91b7b7e2aa5ffc88774ce1aa9aef08d4c709f /fs/buffer.c | |
| parent | 5aa875d2cbee34727963bd81aa992b64480045ca (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.c | 53 |
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++; |
