@@ -4879,25 +4879,29 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
4879
4879
return ret ;
4880
4880
}
4881
4881
4882
+ struct btrfs_uring_encoded_data {
4883
+ struct btrfs_ioctl_encoded_io_args args ;
4884
+ struct iovec iovstack [UIO_FASTIOV ];
4885
+ struct iovec * iov ;
4886
+ struct iov_iter iter ;
4887
+ };
4888
+
4882
4889
static int btrfs_uring_encoded_read (struct io_uring_cmd * cmd , unsigned int issue_flags )
4883
4890
{
4884
4891
size_t copy_end_kernel = offsetofend (struct btrfs_ioctl_encoded_io_args , flags );
4885
4892
size_t copy_end ;
4886
- struct btrfs_ioctl_encoded_io_args args = { 0 };
4887
4893
int ret ;
4888
4894
u64 disk_bytenr , disk_io_size ;
4889
4895
struct file * file ;
4890
4896
struct btrfs_inode * inode ;
4891
4897
struct btrfs_fs_info * fs_info ;
4892
4898
struct extent_io_tree * io_tree ;
4893
- struct iovec iovstack [UIO_FASTIOV ];
4894
- struct iovec * iov = iovstack ;
4895
- struct iov_iter iter ;
4896
4899
loff_t pos ;
4897
4900
struct kiocb kiocb ;
4898
4901
struct extent_state * cached_state = NULL ;
4899
4902
u64 start , lockend ;
4900
4903
void __user * sqe_addr ;
4904
+ struct btrfs_uring_encoded_data * data = io_uring_cmd_get_async_data (cmd )-> op_data ;
4901
4905
4902
4906
if (!capable (CAP_SYS_ADMIN )) {
4903
4907
ret = - EPERM ;
@@ -4911,43 +4915,64 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
4911
4915
4912
4916
if (issue_flags & IO_URING_F_COMPAT ) {
4913
4917
#if defined(CONFIG_64BIT ) && defined(CONFIG_COMPAT )
4914
- struct btrfs_ioctl_encoded_io_args_32 args32 ;
4915
-
4916
4918
copy_end = offsetofend (struct btrfs_ioctl_encoded_io_args_32 , flags );
4917
- if (copy_from_user (& args32 , sqe_addr , copy_end )) {
4918
- ret = - EFAULT ;
4919
- goto out_acct ;
4920
- }
4921
- args .iov = compat_ptr (args32 .iov );
4922
- args .iovcnt = args32 .iovcnt ;
4923
- args .offset = args32 .offset ;
4924
- args .flags = args32 .flags ;
4925
4919
#else
4926
4920
return - ENOTTY ;
4927
4921
#endif
4928
4922
} else {
4929
4923
copy_end = copy_end_kernel ;
4930
- if (copy_from_user (& args , sqe_addr , copy_end )) {
4931
- ret = - EFAULT ;
4924
+ }
4925
+
4926
+ if (!data ) {
4927
+ data = kzalloc (sizeof (* data ), GFP_NOFS );
4928
+ if (!data ) {
4929
+ ret = - ENOMEM ;
4932
4930
goto out_acct ;
4933
4931
}
4934
- }
4935
4932
4936
- if (args .flags != 0 )
4937
- return - EINVAL ;
4933
+ io_uring_cmd_get_async_data (cmd )-> op_data = data ;
4938
4934
4939
- ret = import_iovec (ITER_DEST , args .iov , args .iovcnt , ARRAY_SIZE (iovstack ),
4940
- & iov , & iter );
4941
- if (ret < 0 )
4942
- goto out_acct ;
4935
+ if (issue_flags & IO_URING_F_COMPAT ) {
4936
+ #if defined(CONFIG_64BIT ) && defined(CONFIG_COMPAT )
4937
+ struct btrfs_ioctl_encoded_io_args_32 args32 ;
4943
4938
4944
- if (iov_iter_count (& iter ) == 0 ) {
4945
- ret = 0 ;
4946
- goto out_free ;
4939
+ if (copy_from_user (& args32 , sqe_addr , copy_end )) {
4940
+ ret = - EFAULT ;
4941
+ goto out_acct ;
4942
+ }
4943
+
4944
+ data -> args .iov = compat_ptr (args32 .iov );
4945
+ data -> args .iovcnt = args32 .iovcnt ;
4946
+ data -> args .offset = args32 .offset ;
4947
+ data -> args .flags = args32 .flags ;
4948
+ #endif
4949
+ } else {
4950
+ if (copy_from_user (& data -> args , sqe_addr , copy_end )) {
4951
+ ret = - EFAULT ;
4952
+ goto out_acct ;
4953
+ }
4954
+ }
4955
+
4956
+ if (data -> args .flags != 0 ) {
4957
+ ret = - EINVAL ;
4958
+ goto out_acct ;
4959
+ }
4960
+
4961
+ data -> iov = data -> iovstack ;
4962
+ ret = import_iovec (ITER_DEST , data -> args .iov , data -> args .iovcnt ,
4963
+ ARRAY_SIZE (data -> iovstack ), & data -> iov ,
4964
+ & data -> iter );
4965
+ if (ret < 0 )
4966
+ goto out_acct ;
4967
+
4968
+ if (iov_iter_count (& data -> iter ) == 0 ) {
4969
+ ret = 0 ;
4970
+ goto out_free ;
4971
+ }
4947
4972
}
4948
4973
4949
- pos = args .offset ;
4950
- ret = rw_verify_area (READ , file , & pos , args .len );
4974
+ pos = data -> args .offset ;
4975
+ ret = rw_verify_area (READ , file , & pos , data -> args .len );
4951
4976
if (ret < 0 )
4952
4977
goto out_free ;
4953
4978
@@ -4960,15 +4985,16 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
4960
4985
start = ALIGN_DOWN (pos , fs_info -> sectorsize );
4961
4986
lockend = start + BTRFS_MAX_UNCOMPRESSED - 1 ;
4962
4987
4963
- ret = btrfs_encoded_read (& kiocb , & iter , & args , & cached_state ,
4988
+ ret = btrfs_encoded_read (& kiocb , & data -> iter , & data -> args , & cached_state ,
4964
4989
& disk_bytenr , & disk_io_size );
4965
4990
if (ret < 0 && ret != - EIOCBQUEUED )
4966
4991
goto out_free ;
4967
4992
4968
4993
file_accessed (file );
4969
4994
4970
- if (copy_to_user (sqe_addr + copy_end , (const char * )& args + copy_end_kernel ,
4971
- sizeof (args ) - copy_end_kernel )) {
4995
+ if (copy_to_user (sqe_addr + copy_end ,
4996
+ (const char * )& data -> args + copy_end_kernel ,
4997
+ sizeof (data -> args ) - copy_end_kernel )) {
4972
4998
if (ret == - EIOCBQUEUED ) {
4973
4999
unlock_extent (io_tree , start , lockend , & cached_state );
4974
5000
btrfs_inode_unlock (inode , BTRFS_ILOCK_SHARED );
@@ -4978,40 +5004,22 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
4978
5004
}
4979
5005
4980
5006
if (ret == - EIOCBQUEUED ) {
4981
- u64 count ;
4982
-
4983
- /*
4984
- * If we've optimized things by storing the iovecs on the stack,
4985
- * undo this.
4986
- */
4987
- if (!iov ) {
4988
- iov = kmalloc (sizeof (struct iovec ) * args .iovcnt , GFP_NOFS );
4989
- if (!iov ) {
4990
- unlock_extent (io_tree , start , lockend , & cached_state );
4991
- btrfs_inode_unlock (inode , BTRFS_ILOCK_SHARED );
4992
- ret = - ENOMEM ;
4993
- goto out_acct ;
4994
- }
4995
-
4996
- memcpy (iov , iovstack , sizeof (struct iovec ) * args .iovcnt );
4997
- }
4998
-
4999
- count = min_t (u64 , iov_iter_count (& iter ), disk_io_size );
5007
+ u64 count = min_t (u64 , iov_iter_count (& data -> iter ), disk_io_size );
5000
5008
5001
5009
/* Match ioctl by not returning past EOF if uncompressed. */
5002
- if (!args .compression )
5003
- count = min_t (u64 , count , args .len );
5010
+ if (!data -> args .compression )
5011
+ count = min_t (u64 , count , data -> args .len );
5004
5012
5005
- ret = btrfs_uring_read_extent (& kiocb , & iter , start , lockend ,
5006
- cached_state , disk_bytenr ,
5007
- disk_io_size , count ,
5008
- args . compression , iov , cmd );
5013
+ ret = btrfs_uring_read_extent (& kiocb , & data -> iter , start , lockend ,
5014
+ cached_state , disk_bytenr , disk_io_size ,
5015
+ count , data -> args . compression ,
5016
+ data -> iov , cmd );
5009
5017
5010
5018
goto out_acct ;
5011
5019
}
5012
5020
5013
5021
out_free :
5014
- kfree (iov );
5022
+ kfree (data -> iov );
5015
5023
5016
5024
out_acct :
5017
5025
if (ret > 0 )
0 commit comments