diff mbox series

exfat: use iter_file_splice_write

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

Commit Message

Eric Sandeen May 2, 2020, 1:34 a.m. UTC
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...

Comments

Namjae Jeon May 3, 2020, 2:47 p.m. UTC | #1
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 mbox series

Patch

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 = {