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 ...
This commit is contained in:
36
mm/filemap.c
36
mm/filemap.c
@@ -1275,7 +1275,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
{
|
||||
struct file *filp = iocb->ki_filp;
|
||||
ssize_t retval;
|
||||
unsigned long seg;
|
||||
unsigned long seg = 0;
|
||||
size_t count;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
|
||||
@@ -1302,21 +1302,47 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
retval = mapping->a_ops->direct_IO(READ, iocb,
|
||||
iov, pos, nr_segs);
|
||||
}
|
||||
if (retval > 0)
|
||||
if (retval > 0) {
|
||||
*ppos = pos + retval;
|
||||
if (retval) {
|
||||
count -= retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Btrfs can have a short DIO read if we encounter
|
||||
* compressed extents, so if there was an error, or if
|
||||
* we've already read everything we wanted to, or if
|
||||
* there was a short read because we hit EOF, go ahead
|
||||
* and return. Otherwise fallthrough to buffered io for
|
||||
* the rest of the read.
|
||||
*/
|
||||
if (retval < 0 || !count || *ppos >= size) {
|
||||
file_accessed(filp);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = retval;
|
||||
for (seg = 0; seg < nr_segs; seg++) {
|
||||
read_descriptor_t desc;
|
||||
loff_t offset = 0;
|
||||
|
||||
/*
|
||||
* If we did a short DIO read we need to skip the section of the
|
||||
* iov that we've already read data into.
|
||||
*/
|
||||
if (count) {
|
||||
if (count > iov[seg].iov_len) {
|
||||
count -= iov[seg].iov_len;
|
||||
continue;
|
||||
}
|
||||
offset = count;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
desc.written = 0;
|
||||
desc.arg.buf = iov[seg].iov_base;
|
||||
desc.count = iov[seg].iov_len;
|
||||
desc.arg.buf = iov[seg].iov_base + offset;
|
||||
desc.count = iov[seg].iov_len - offset;
|
||||
if (desc.count == 0)
|
||||
continue;
|
||||
desc.error = 0;
|
||||
|
Reference in New Issue
Block a user