diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 13:43:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 13:43:44 -0400 |
commit | 105a048a4f35f7a74c7cc20b36dd83658b6ec232 (patch) | |
tree | 043b1110cda0042ba35d8aae59382bb094d0af3f /mm/filemap.c | |
parent | 00b9b0af5887fed54e899e3b7f5c2ccf5e739def (diff) | |
parent | 9aeead73782c4b8e2a91def36dbf95db28605c95 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (27 commits)
Btrfs: add more error checking to btrfs_dirty_inode
Btrfs: allow unaligned DIO
Btrfs: drop verbose enospc printk
Btrfs: Fix block generation verification race
Btrfs: fix preallocation and nodatacow checks in O_DIRECT
Btrfs: avoid ENOSPC errors in btrfs_dirty_inode
Btrfs: move O_DIRECT space reservation to btrfs_direct_IO
Btrfs: rework O_DIRECT enospc handling
Btrfs: use async helpers for DIO write checksumming
Btrfs: don't walk around with task->state != TASK_RUNNING
Btrfs: do aio_write instead of write
Btrfs: add basic DIO read/write support
direct-io: do not merge logically non-contiguous requests
direct-io: add a hook for the fs to provide its own submit_bio function
fs: allow short direct-io reads to be completed via buffered IO
Btrfs: Metadata ENOSPC handling for balance
Btrfs: Pre-allocate space for data relocation
Btrfs: Metadata ENOSPC handling for tree log
Btrfs: Metadata reservation for orphan inodes
Btrfs: Introduce global metadata reservation
...
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 35e12d186566..45a2d18df849 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1275,7 +1275,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
1275 | { | 1275 | { |
1276 | struct file *filp = iocb->ki_filp; | 1276 | struct file *filp = iocb->ki_filp; |
1277 | ssize_t retval; | 1277 | ssize_t retval; |
1278 | unsigned long seg; | 1278 | unsigned long seg = 0; |
1279 | size_t count; | 1279 | size_t count; |
1280 | loff_t *ppos = &iocb->ki_pos; | 1280 | loff_t *ppos = &iocb->ki_pos; |
1281 | 1281 | ||
@@ -1302,21 +1302,47 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
1302 | retval = mapping->a_ops->direct_IO(READ, iocb, | 1302 | retval = mapping->a_ops->direct_IO(READ, iocb, |
1303 | iov, pos, nr_segs); | 1303 | iov, pos, nr_segs); |
1304 | } | 1304 | } |
1305 | if (retval > 0) | 1305 | if (retval > 0) { |
1306 | *ppos = pos + retval; | 1306 | *ppos = pos + retval; |
1307 | if (retval) { | 1307 | count -= retval; |
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | * Btrfs can have a short DIO read if we encounter | ||
1312 | * compressed extents, so if there was an error, or if | ||
1313 | * we've already read everything we wanted to, or if | ||
1314 | * there was a short read because we hit EOF, go ahead | ||
1315 | * and return. Otherwise fallthrough to buffered io for | ||
1316 | * the rest of the read. | ||
1317 | */ | ||
1318 | if (retval < 0 || !count || *ppos >= size) { | ||
1308 | file_accessed(filp); | 1319 | file_accessed(filp); |
1309 | goto out; | 1320 | goto out; |
1310 | } | 1321 | } |
1311 | } | 1322 | } |
1312 | } | 1323 | } |
1313 | 1324 | ||
1325 | count = retval; | ||
1314 | for (seg = 0; seg < nr_segs; seg++) { | 1326 | for (seg = 0; seg < nr_segs; seg++) { |
1315 | read_descriptor_t desc; | 1327 | read_descriptor_t desc; |
1328 | loff_t offset = 0; | ||
1329 | |||
1330 | /* | ||
1331 | * If we did a short DIO read we need to skip the section of the | ||
1332 | * iov that we've already read data into. | ||
1333 | */ | ||
1334 | if (count) { | ||
1335 | if (count > iov[seg].iov_len) { | ||
1336 | count -= iov[seg].iov_len; | ||
1337 | continue; | ||
1338 | } | ||
1339 | offset = count; | ||
1340 | count = 0; | ||
1341 | } | ||
1316 | 1342 | ||
1317 | desc.written = 0; | 1343 | desc.written = 0; |
1318 | desc.arg.buf = iov[seg].iov_base; | 1344 | desc.arg.buf = iov[seg].iov_base + offset; |
1319 | desc.count = iov[seg].iov_len; | 1345 | desc.count = iov[seg].iov_len - offset; |
1320 | if (desc.count == 0) | 1346 | if (desc.count == 0) |
1321 | continue; | 1347 | continue; |
1322 | desc.error = 0; | 1348 | desc.error = 0; |