Message ID | f7b13155-5f56-1d14-4c26-e1fea8d04a62@sandeen.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | exfat: use iter_file_splice_write | expand |
2020-05-02 10:34 GMT+09:00, Eric Sandeen <sandeen@sandeen.net>: > Doing copy_file_range() on exfat with a file opened for direct IO leads > to an -EFAULT: > > # xfs_io -f -d -c "truncate 32768" \ > -c "copy_range -d 16384 -l 16384 -f 0" /mnt/test/junk > copy_range: Bad address > > and the reason seems to be that we go through: > > default_file_splice_write > splice_from_pipe > __splice_from_pipe > write_pipe_buf > __kernel_write > new_sync_write > generic_file_write_iter > generic_file_direct_write > exfat_direct_IO > do_blockdev_direct_IO > iov_iter_get_pages > > and land in iterate_all_kinds(), which does "return -EFAULT" for our kvec > iter. > > Setting exfat's splice_write to iter_file_splice_write fixes this and lets > fsx (which originally detected the problem) run to success from the > xfstests > harness. > > Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Applied:) Thanks! > --- > > I know that's not a good changelog; I conferred with viro about whether > this > is correct, but I still don't have a great explanation, so feel free to fix > up > the changelog to be more informative if the change is otherwise correct... > > diff --git a/fs/exfat/file.c b/fs/exfat/file.c > index 4f76764165cf..c9db8eb0cfc3 100644 > --- a/fs/exfat/file.c > +++ b/fs/exfat/file.c > @@ -348,12 +348,13 @@ int exfat_setattr(struct dentry *dentry, struct iattr > *attr) > } > > const struct file_operations exfat_file_operations = { > - .llseek = generic_file_llseek, > - .read_iter = generic_file_read_iter, > - .write_iter = generic_file_write_iter, > - .mmap = generic_file_mmap, > - .fsync = generic_file_fsync, > - .splice_read = generic_file_splice_read, > + .llseek = generic_file_llseek, > + .read_iter = generic_file_read_iter, > + .write_iter = generic_file_write_iter, > + .mmap = generic_file_mmap, > + .fsync = generic_file_fsync, > + .splice_read = generic_file_splice_read, > + .splice_write = iter_file_splice_write, > }; > > const struct inode_operations exfat_file_inode_operations = { > > >
diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 4f76764165cf..c9db8eb0cfc3 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -348,12 +348,13 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr) } const struct file_operations exfat_file_operations = { - .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .mmap = generic_file_mmap, - .fsync = generic_file_fsync, - .splice_read = generic_file_splice_read, + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, + .mmap = generic_file_mmap, + .fsync = generic_file_fsync, + .splice_read = generic_file_splice_read, + .splice_write = iter_file_splice_write, }; const struct inode_operations exfat_file_inode_operations = {
Doing copy_file_range() on exfat with a file opened for direct IO leads to an -EFAULT: # xfs_io -f -d -c "truncate 32768" \ -c "copy_range -d 16384 -l 16384 -f 0" /mnt/test/junk copy_range: Bad address and the reason seems to be that we go through: default_file_splice_write splice_from_pipe __splice_from_pipe write_pipe_buf __kernel_write new_sync_write generic_file_write_iter generic_file_direct_write exfat_direct_IO do_blockdev_direct_IO iov_iter_get_pages and land in iterate_all_kinds(), which does "return -EFAULT" for our kvec iter. Setting exfat's splice_write to iter_file_splice_write fixes this and lets fsx (which originally detected the problem) run to success from the xfstests harness. Signed-off-by: Eric Sandeen <sandeen@sandeen.net> --- I know that's not a good changelog; I conferred with viro about whether this is correct, but I still don't have a great explanation, so feel free to fix up the changelog to be more informative if the change is otherwise correct...