aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 13:43:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 13:43:44 -0400
commit105a048a4f35f7a74c7cc20b36dd83658b6ec232 (patch)
tree043b1110cda0042ba35d8aae59382bb094d0af3f /mm/filemap.c
parent00b9b0af5887fed54e899e3b7f5c2ccf5e739def (diff)
parent9aeead73782c4b8e2a91def36dbf95db28605c95 (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.c36
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;