diff options
author | Josef Bacik <josef@redhat.com> | 2010-05-23 11:00:55 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2010-05-25 10:34:55 -0400 |
commit | facd07b07d2a7988f5ce849558838cc953847637 (patch) | |
tree | 269200329390f450d2bc7f0858a8ed114a418374 /include | |
parent | 66f998f611897319b555364cefd5d6e88a205866 (diff) |
direct-io: add a hook for the fs to provide its own submit_bio function
Because BTRFS can do RAID and such, we need our own submit hook so we can setup
the bio's in the correct fashion, and handle checksum errors properly. So there
are a few changes here
1) The submit_io hook. This is straightforward, just call this instead of
submit_bio.
2) Allow the fs to return -ENOTBLK for reads. Usually this has only worked for
writes, since writes can fallback onto buffered IO. But BTRFS needs the option
of falling back on buffered IO if it encounters a compressed extent, since we
need to read the entire extent in and decompress it. So if we get -ENOTBLK back
from get_block we'll return back and fallback on buffered just like the write
case.
I've tested these changes with fsx and everything seems to work. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/fs.h | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index 44f35aea2f1f..10704f0086c8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2250,10 +2250,15 @@ static inline int xip_truncate_page(struct address_space *mapping, loff_t from) | |||
2250 | #endif | 2250 | #endif |
2251 | 2251 | ||
2252 | #ifdef CONFIG_BLOCK | 2252 | #ifdef CONFIG_BLOCK |
2253 | struct bio; | ||
2254 | typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode, | ||
2255 | loff_t file_offset); | ||
2256 | void dio_end_io(struct bio *bio, int error); | ||
2257 | |||
2253 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | 2258 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
2254 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | 2259 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
2255 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | 2260 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, |
2256 | int lock_type); | 2261 | dio_submit_t submit_io, int lock_type); |
2257 | 2262 | ||
2258 | enum { | 2263 | enum { |
2259 | /* need locking between buffered and direct access */ | 2264 | /* need locking between buffered and direct access */ |
@@ -2269,7 +2274,7 @@ static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, | |||
2269 | dio_iodone_t end_io) | 2274 | dio_iodone_t end_io) |
2270 | { | 2275 | { |
2271 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | 2276 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, |
2272 | nr_segs, get_block, end_io, | 2277 | nr_segs, get_block, end_io, NULL, |
2273 | DIO_LOCKING | DIO_SKIP_HOLES); | 2278 | DIO_LOCKING | DIO_SKIP_HOLES); |
2274 | } | 2279 | } |
2275 | 2280 | ||
@@ -2279,7 +2284,7 @@ static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb, | |||
2279 | dio_iodone_t end_io) | 2284 | dio_iodone_t end_io) |
2280 | { | 2285 | { |
2281 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | 2286 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, |
2282 | nr_segs, get_block, end_io, 0); | 2287 | nr_segs, get_block, end_io, NULL, 0); |
2283 | } | 2288 | } |
2284 | #endif | 2289 | #endif |
2285 | 2290 | ||