diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-05 17:35:57 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-05 17:35:57 -0400 |
| commit | 89fbf5384ddf666a595eb6562dc63fcbfeb8f6a5 (patch) | |
| tree | fc2de270b1dae61f850e9aff0784a672667e2acc | |
| parent | 4be95131bf3bca97b6a7db9c6fb63db2cb94da06 (diff) | |
| parent | a4058c5bce8aded1a12a59990e84e481a96fb490 (diff) | |
Merge branch 'work.read_write' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull read/write updates from Al Viro:
"Christoph's fs/read_write.c series - consolidation and cleanups"
* 'work.read_write' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
nfsd: remove nfsd_vfs_read
nfsd: use vfs_iter_read/write
fs: implement vfs_iter_write using do_iter_write
fs: implement vfs_iter_read using do_iter_read
fs: move more code into do_iter_read/do_iter_write
fs: remove __do_readv_writev
fs: remove do_compat_readv_writev
fs: remove do_readv_writev
| -rw-r--r-- | drivers/block/loop.c | 6 | ||||
| -rw-r--r-- | drivers/target/target_core_file.c | 6 | ||||
| -rw-r--r-- | fs/coda/file.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 34 | ||||
| -rw-r--r-- | fs/read_write.c | 220 | ||||
| -rw-r--r-- | fs/splice.c | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 6 |
7 files changed, 117 insertions, 161 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0de11444e317..ef8334949b42 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -273,7 +273,7 @@ static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos) | |||
| 273 | iov_iter_bvec(&i, ITER_BVEC, bvec, 1, bvec->bv_len); | 273 | iov_iter_bvec(&i, ITER_BVEC, bvec, 1, bvec->bv_len); |
| 274 | 274 | ||
| 275 | file_start_write(file); | 275 | file_start_write(file); |
| 276 | bw = vfs_iter_write(file, &i, ppos); | 276 | bw = vfs_iter_write(file, &i, ppos, 0); |
| 277 | file_end_write(file); | 277 | file_end_write(file); |
| 278 | 278 | ||
| 279 | if (likely(bw == bvec->bv_len)) | 279 | if (likely(bw == bvec->bv_len)) |
| @@ -349,7 +349,7 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq, | |||
| 349 | 349 | ||
| 350 | rq_for_each_segment(bvec, rq, iter) { | 350 | rq_for_each_segment(bvec, rq, iter) { |
| 351 | iov_iter_bvec(&i, ITER_BVEC, &bvec, 1, bvec.bv_len); | 351 | iov_iter_bvec(&i, ITER_BVEC, &bvec, 1, bvec.bv_len); |
| 352 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos); | 352 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); |
| 353 | if (len < 0) | 353 | if (len < 0) |
| 354 | return len; | 354 | return len; |
| 355 | 355 | ||
| @@ -390,7 +390,7 @@ static int lo_read_transfer(struct loop_device *lo, struct request *rq, | |||
| 390 | b.bv_len = bvec.bv_len; | 390 | b.bv_len = bvec.bv_len; |
| 391 | 391 | ||
| 392 | iov_iter_bvec(&i, ITER_BVEC, &b, 1, b.bv_len); | 392 | iov_iter_bvec(&i, ITER_BVEC, &b, 1, b.bv_len); |
| 393 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos); | 393 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); |
| 394 | if (len < 0) { | 394 | if (len < 0) { |
| 395 | ret = len; | 395 | ret = len; |
| 396 | goto out_free_page; | 396 | goto out_free_page; |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 73b8f93a5fef..e921948415c7 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
| @@ -273,9 +273,9 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd, | |||
| 273 | 273 | ||
| 274 | iov_iter_bvec(&iter, ITER_BVEC, bvec, sgl_nents, len); | 274 | iov_iter_bvec(&iter, ITER_BVEC, bvec, sgl_nents, len); |
| 275 | if (is_write) | 275 | if (is_write) |
| 276 | ret = vfs_iter_write(fd, &iter, &pos); | 276 | ret = vfs_iter_write(fd, &iter, &pos, 0); |
| 277 | else | 277 | else |
| 278 | ret = vfs_iter_read(fd, &iter, &pos); | 278 | ret = vfs_iter_read(fd, &iter, &pos, 0); |
| 279 | 279 | ||
| 280 | if (is_write) { | 280 | if (is_write) { |
| 281 | if (ret < 0 || ret != data_length) { | 281 | if (ret < 0 || ret != data_length) { |
| @@ -409,7 +409,7 @@ fd_execute_write_same(struct se_cmd *cmd) | |||
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len); | 411 | iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len); |
| 412 | ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos); | 412 | ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos, 0); |
| 413 | 413 | ||
| 414 | kfree(bvec); | 414 | kfree(bvec); |
| 415 | if (ret < 0 || ret != len) { | 415 | if (ret < 0 || ret != len) { |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 9d956cd6d46f..363402fcb3ed 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
| @@ -34,7 +34,7 @@ coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | |||
| 34 | 34 | ||
| 35 | BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); | 35 | BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); |
| 36 | 36 | ||
| 37 | return vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos); | 37 | return vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos, 0); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | static ssize_t | 40 | static ssize_t |
| @@ -51,7 +51,7 @@ coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to) | |||
| 51 | host_file = cfi->cfi_container; | 51 | host_file = cfi->cfi_container; |
| 52 | file_start_write(host_file); | 52 | file_start_write(host_file); |
| 53 | inode_lock(coda_inode); | 53 | inode_lock(coda_inode); |
| 54 | ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos); | 54 | ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos, 0); |
| 55 | coda_inode->i_size = file_inode(host_file)->i_size; | 55 | coda_inode->i_size = file_inode(host_file)->i_size; |
| 56 | coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9; | 56 | coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9; |
| 57 | coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode); | 57 | coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6eef95c585e3..38d0383dc7f9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -911,24 +911,13 @@ __be32 nfsd_splice_read(struct svc_rqst *rqstp, | |||
| 911 | __be32 nfsd_readv(struct file *file, loff_t offset, struct kvec *vec, int vlen, | 911 | __be32 nfsd_readv(struct file *file, loff_t offset, struct kvec *vec, int vlen, |
| 912 | unsigned long *count) | 912 | unsigned long *count) |
| 913 | { | 913 | { |
| 914 | mm_segment_t oldfs; | 914 | struct iov_iter iter; |
| 915 | int host_err; | 915 | int host_err; |
| 916 | 916 | ||
| 917 | oldfs = get_fs(); | 917 | iov_iter_kvec(&iter, READ | ITER_KVEC, vec, vlen, *count); |
| 918 | set_fs(KERNEL_DS); | 918 | host_err = vfs_iter_read(file, &iter, &offset, 0); |
| 919 | host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset, 0); | ||
| 920 | set_fs(oldfs); | ||
| 921 | return nfsd_finish_read(file, count, host_err); | ||
| 922 | } | ||
| 923 | 919 | ||
| 924 | static __be32 | 920 | return nfsd_finish_read(file, count, host_err); |
| 925 | nfsd_vfs_read(struct svc_rqst *rqstp, struct file *file, | ||
| 926 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | ||
| 927 | { | ||
| 928 | if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags)) | ||
| 929 | return nfsd_splice_read(rqstp, file, offset, count); | ||
| 930 | else | ||
| 931 | return nfsd_readv(file, offset, vec, vlen, count); | ||
| 932 | } | 921 | } |
| 933 | 922 | ||
| 934 | /* | 923 | /* |
| @@ -974,7 +963,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 974 | unsigned long *cnt, int stable) | 963 | unsigned long *cnt, int stable) |
| 975 | { | 964 | { |
| 976 | struct svc_export *exp; | 965 | struct svc_export *exp; |
| 977 | mm_segment_t oldfs; | 966 | struct iov_iter iter; |
| 978 | __be32 err = 0; | 967 | __be32 err = 0; |
| 979 | int host_err; | 968 | int host_err; |
| 980 | int use_wgather; | 969 | int use_wgather; |
| @@ -1000,10 +989,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 1000 | if (stable && !use_wgather) | 989 | if (stable && !use_wgather) |
| 1001 | flags |= RWF_SYNC; | 990 | flags |= RWF_SYNC; |
| 1002 | 991 | ||
| 1003 | /* Write the data. */ | 992 | iov_iter_kvec(&iter, WRITE | ITER_KVEC, vec, vlen, *cnt); |
| 1004 | oldfs = get_fs(); set_fs(KERNEL_DS); | 993 | host_err = vfs_iter_write(file, &iter, &pos, flags); |
| 1005 | host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &pos, flags); | ||
| 1006 | set_fs(oldfs); | ||
| 1007 | if (host_err < 0) | 994 | if (host_err < 0) |
| 1008 | goto out_nfserr; | 995 | goto out_nfserr; |
| 1009 | *cnt = host_err; | 996 | *cnt = host_err; |
| @@ -1044,7 +1031,12 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1044 | ra = nfsd_init_raparms(file); | 1031 | ra = nfsd_init_raparms(file); |
| 1045 | 1032 | ||
| 1046 | trace_read_opened(rqstp, fhp, offset, vlen); | 1033 | trace_read_opened(rqstp, fhp, offset, vlen); |
| 1047 | err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count); | 1034 | |
| 1035 | if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags)) | ||
| 1036 | err = nfsd_splice_read(rqstp, file, offset, count); | ||
| 1037 | else | ||
| 1038 | err = nfsd_readv(file, offset, vec, vlen, count); | ||
| 1039 | |||
| 1048 | trace_read_io_done(rqstp, fhp, offset, vlen); | 1040 | trace_read_io_done(rqstp, fhp, offset, vlen); |
| 1049 | 1041 | ||
| 1050 | if (ra) | 1042 | if (ra) |
diff --git a/fs/read_write.c b/fs/read_write.c index d591eeed061f..a2cbc8303dae 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -356,46 +356,6 @@ out_putf: | |||
| 356 | } | 356 | } |
| 357 | #endif | 357 | #endif |
| 358 | 358 | ||
| 359 | ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos) | ||
| 360 | { | ||
| 361 | struct kiocb kiocb; | ||
| 362 | ssize_t ret; | ||
| 363 | |||
| 364 | if (!file->f_op->read_iter) | ||
| 365 | return -EINVAL; | ||
| 366 | |||
| 367 | init_sync_kiocb(&kiocb, file); | ||
| 368 | kiocb.ki_pos = *ppos; | ||
| 369 | |||
| 370 | iter->type |= READ; | ||
| 371 | ret = call_read_iter(file, &kiocb, iter); | ||
| 372 | BUG_ON(ret == -EIOCBQUEUED); | ||
| 373 | if (ret > 0) | ||
| 374 | *ppos = kiocb.ki_pos; | ||
| 375 | return ret; | ||
| 376 | } | ||
| 377 | EXPORT_SYMBOL(vfs_iter_read); | ||
| 378 | |||
| 379 | ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) | ||
| 380 | { | ||
| 381 | struct kiocb kiocb; | ||
| 382 | ssize_t ret; | ||
| 383 | |||
| 384 | if (!file->f_op->write_iter) | ||
| 385 | return -EINVAL; | ||
| 386 | |||
| 387 | init_sync_kiocb(&kiocb, file); | ||
| 388 | kiocb.ki_pos = *ppos; | ||
| 389 | |||
| 390 | iter->type |= WRITE; | ||
| 391 | ret = call_write_iter(file, &kiocb, iter); | ||
| 392 | BUG_ON(ret == -EIOCBQUEUED); | ||
| 393 | if (ret > 0) | ||
| 394 | *ppos = kiocb.ki_pos; | ||
| 395 | return ret; | ||
| 396 | } | ||
| 397 | EXPORT_SYMBOL(vfs_iter_write); | ||
| 398 | |||
| 399 | int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) | 359 | int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) |
| 400 | { | 360 | { |
| 401 | struct inode *inode; | 361 | struct inode *inode; |
| @@ -910,86 +870,114 @@ out: | |||
| 910 | } | 870 | } |
| 911 | #endif | 871 | #endif |
| 912 | 872 | ||
| 913 | static ssize_t __do_readv_writev(int type, struct file *file, | 873 | static ssize_t do_iter_read(struct file *file, struct iov_iter *iter, |
| 914 | struct iov_iter *iter, loff_t *pos, int flags) | 874 | loff_t *pos, int flags) |
| 915 | { | 875 | { |
| 916 | size_t tot_len; | 876 | size_t tot_len; |
| 917 | ssize_t ret = 0; | 877 | ssize_t ret = 0; |
| 918 | 878 | ||
| 879 | if (!(file->f_mode & FMODE_READ)) | ||
| 880 | return -EBADF; | ||
| 881 | if (!(file->f_mode & FMODE_CAN_READ)) | ||
| 882 | return -EINVAL; | ||
| 883 | |||
| 919 | tot_len = iov_iter_count(iter); | 884 | tot_len = iov_iter_count(iter); |
| 920 | if (!tot_len) | 885 | if (!tot_len) |
| 921 | goto out; | 886 | goto out; |
| 922 | ret = rw_verify_area(type, file, pos, tot_len); | 887 | ret = rw_verify_area(READ, file, pos, tot_len); |
| 923 | if (ret < 0) | 888 | if (ret < 0) |
| 924 | goto out; | 889 | return ret; |
| 925 | |||
| 926 | if (type != READ) | ||
| 927 | file_start_write(file); | ||
| 928 | 890 | ||
| 929 | if ((type == READ && file->f_op->read_iter) || | 891 | if (file->f_op->read_iter) |
| 930 | (type == WRITE && file->f_op->write_iter)) | 892 | ret = do_iter_readv_writev(file, iter, pos, READ, flags); |
| 931 | ret = do_iter_readv_writev(file, iter, pos, type, flags); | ||
| 932 | else | 893 | else |
| 933 | ret = do_loop_readv_writev(file, iter, pos, type, flags); | 894 | ret = do_loop_readv_writev(file, iter, pos, READ, flags); |
| 934 | |||
| 935 | if (type != READ) | ||
| 936 | file_end_write(file); | ||
| 937 | |||
| 938 | out: | 895 | out: |
| 939 | if ((ret + (type == READ)) > 0) { | 896 | if (ret >= 0) |
| 940 | if (type == READ) | 897 | fsnotify_access(file); |
| 941 | fsnotify_access(file); | ||
| 942 | else | ||
| 943 | fsnotify_modify(file); | ||
| 944 | } | ||
| 945 | return ret; | 898 | return ret; |
| 946 | } | 899 | } |
| 947 | 900 | ||
| 948 | static ssize_t do_readv_writev(int type, struct file *file, | 901 | ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos, |
| 949 | const struct iovec __user *uvector, | 902 | int flags) |
| 950 | unsigned long nr_segs, loff_t *pos, | ||
| 951 | int flags) | ||
| 952 | { | 903 | { |
| 953 | struct iovec iovstack[UIO_FASTIOV]; | 904 | if (!file->f_op->read_iter) |
| 954 | struct iovec *iov = iovstack; | 905 | return -EINVAL; |
| 955 | struct iov_iter iter; | 906 | return do_iter_read(file, iter, ppos, flags); |
| 956 | ssize_t ret; | 907 | } |
| 908 | EXPORT_SYMBOL(vfs_iter_read); | ||
| 909 | |||
| 910 | static ssize_t do_iter_write(struct file *file, struct iov_iter *iter, | ||
| 911 | loff_t *pos, int flags) | ||
| 912 | { | ||
| 913 | size_t tot_len; | ||
| 914 | ssize_t ret = 0; | ||
| 915 | |||
| 916 | if (!(file->f_mode & FMODE_WRITE)) | ||
| 917 | return -EBADF; | ||
| 918 | if (!(file->f_mode & FMODE_CAN_WRITE)) | ||
| 919 | return -EINVAL; | ||
| 957 | 920 | ||
| 958 | ret = import_iovec(type, uvector, nr_segs, | 921 | tot_len = iov_iter_count(iter); |
| 959 | ARRAY_SIZE(iovstack), &iov, &iter); | 922 | if (!tot_len) |
| 923 | return 0; | ||
| 924 | ret = rw_verify_area(WRITE, file, pos, tot_len); | ||
| 960 | if (ret < 0) | 925 | if (ret < 0) |
| 961 | return ret; | 926 | return ret; |
| 962 | 927 | ||
| 963 | ret = __do_readv_writev(type, file, &iter, pos, flags); | 928 | file_start_write(file); |
| 964 | kfree(iov); | 929 | if (file->f_op->write_iter) |
| 965 | 930 | ret = do_iter_readv_writev(file, iter, pos, WRITE, flags); | |
| 931 | else | ||
| 932 | ret = do_loop_readv_writev(file, iter, pos, WRITE, flags); | ||
| 933 | file_end_write(file); | ||
| 934 | if (ret > 0) | ||
| 935 | fsnotify_modify(file); | ||
| 966 | return ret; | 936 | return ret; |
| 967 | } | 937 | } |
| 968 | 938 | ||
| 939 | ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos, | ||
| 940 | int flags) | ||
| 941 | { | ||
| 942 | if (!file->f_op->write_iter) | ||
| 943 | return -EINVAL; | ||
| 944 | return do_iter_write(file, iter, ppos, flags); | ||
| 945 | } | ||
| 946 | EXPORT_SYMBOL(vfs_iter_write); | ||
| 947 | |||
| 969 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, | 948 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, |
| 970 | unsigned long vlen, loff_t *pos, int flags) | 949 | unsigned long vlen, loff_t *pos, int flags) |
| 971 | { | 950 | { |
| 972 | if (!(file->f_mode & FMODE_READ)) | 951 | struct iovec iovstack[UIO_FASTIOV]; |
| 973 | return -EBADF; | 952 | struct iovec *iov = iovstack; |
| 974 | if (!(file->f_mode & FMODE_CAN_READ)) | 953 | struct iov_iter iter; |
| 975 | return -EINVAL; | 954 | ssize_t ret; |
| 976 | 955 | ||
| 977 | return do_readv_writev(READ, file, vec, vlen, pos, flags); | 956 | ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); |
| 978 | } | 957 | if (ret >= 0) { |
| 958 | ret = do_iter_read(file, &iter, pos, flags); | ||
| 959 | kfree(iov); | ||
| 960 | } | ||
| 979 | 961 | ||
| 962 | return ret; | ||
| 963 | } | ||
| 980 | EXPORT_SYMBOL(vfs_readv); | 964 | EXPORT_SYMBOL(vfs_readv); |
| 981 | 965 | ||
| 982 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, | 966 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, |
| 983 | unsigned long vlen, loff_t *pos, int flags) | 967 | unsigned long vlen, loff_t *pos, int flags) |
| 984 | { | 968 | { |
| 985 | if (!(file->f_mode & FMODE_WRITE)) | 969 | struct iovec iovstack[UIO_FASTIOV]; |
| 986 | return -EBADF; | 970 | struct iovec *iov = iovstack; |
| 987 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 971 | struct iov_iter iter; |
| 988 | return -EINVAL; | 972 | ssize_t ret; |
| 989 | 973 | ||
| 990 | return do_readv_writev(WRITE, file, vec, vlen, pos, flags); | 974 | ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); |
| 975 | if (ret >= 0) { | ||
| 976 | ret = do_iter_write(file, &iter, pos, flags); | ||
| 977 | kfree(iov); | ||
| 978 | } | ||
| 979 | return ret; | ||
| 991 | } | 980 | } |
| 992 | |||
| 993 | EXPORT_SYMBOL(vfs_writev); | 981 | EXPORT_SYMBOL(vfs_writev); |
| 994 | 982 | ||
| 995 | static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec, | 983 | static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec, |
| @@ -1137,44 +1125,20 @@ SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec, | |||
| 1137 | } | 1125 | } |
| 1138 | 1126 | ||
| 1139 | #ifdef CONFIG_COMPAT | 1127 | #ifdef CONFIG_COMPAT |
| 1140 | 1128 | static size_t compat_readv(struct file *file, | |
| 1141 | static ssize_t compat_do_readv_writev(int type, struct file *file, | 1129 | const struct compat_iovec __user *vec, |
| 1142 | const struct compat_iovec __user *uvector, | 1130 | unsigned long vlen, loff_t *pos, int flags) |
| 1143 | unsigned long nr_segs, loff_t *pos, | ||
| 1144 | int flags) | ||
| 1145 | { | 1131 | { |
| 1146 | struct iovec iovstack[UIO_FASTIOV]; | 1132 | struct iovec iovstack[UIO_FASTIOV]; |
| 1147 | struct iovec *iov = iovstack; | 1133 | struct iovec *iov = iovstack; |
| 1148 | struct iov_iter iter; | 1134 | struct iov_iter iter; |
| 1149 | ssize_t ret; | 1135 | ssize_t ret; |
| 1150 | 1136 | ||
| 1151 | ret = compat_import_iovec(type, uvector, nr_segs, | 1137 | ret = compat_import_iovec(READ, vec, vlen, UIO_FASTIOV, &iov, &iter); |
| 1152 | UIO_FASTIOV, &iov, &iter); | 1138 | if (ret >= 0) { |
| 1153 | if (ret < 0) | 1139 | ret = do_iter_read(file, &iter, pos, flags); |
| 1154 | return ret; | 1140 | kfree(iov); |
| 1155 | 1141 | } | |
| 1156 | ret = __do_readv_writev(type, file, &iter, pos, flags); | ||
| 1157 | kfree(iov); | ||
| 1158 | |||
| 1159 | return ret; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | static size_t compat_readv(struct file *file, | ||
| 1163 | const struct compat_iovec __user *vec, | ||
| 1164 | unsigned long vlen, loff_t *pos, int flags) | ||
| 1165 | { | ||
| 1166 | ssize_t ret = -EBADF; | ||
| 1167 | |||
| 1168 | if (!(file->f_mode & FMODE_READ)) | ||
| 1169 | goto out; | ||
| 1170 | |||
| 1171 | ret = -EINVAL; | ||
| 1172 | if (!(file->f_mode & FMODE_CAN_READ)) | ||
| 1173 | goto out; | ||
| 1174 | |||
| 1175 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos, flags); | ||
| 1176 | |||
| 1177 | out: | ||
| 1178 | if (ret > 0) | 1142 | if (ret > 0) |
| 1179 | add_rchar(current, ret); | 1143 | add_rchar(current, ret); |
| 1180 | inc_syscr(current); | 1144 | inc_syscr(current); |
| @@ -1270,18 +1234,16 @@ static size_t compat_writev(struct file *file, | |||
| 1270 | const struct compat_iovec __user *vec, | 1234 | const struct compat_iovec __user *vec, |
| 1271 | unsigned long vlen, loff_t *pos, int flags) | 1235 | unsigned long vlen, loff_t *pos, int flags) |
| 1272 | { | 1236 | { |
| 1273 | ssize_t ret = -EBADF; | 1237 | struct iovec iovstack[UIO_FASTIOV]; |
| 1274 | 1238 | struct iovec *iov = iovstack; | |
| 1275 | if (!(file->f_mode & FMODE_WRITE)) | 1239 | struct iov_iter iter; |
| 1276 | goto out; | 1240 | ssize_t ret; |
| 1277 | |||
| 1278 | ret = -EINVAL; | ||
| 1279 | if (!(file->f_mode & FMODE_CAN_WRITE)) | ||
| 1280 | goto out; | ||
| 1281 | |||
| 1282 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, flags); | ||
| 1283 | 1241 | ||
| 1284 | out: | 1242 | ret = compat_import_iovec(WRITE, vec, vlen, UIO_FASTIOV, &iov, &iter); |
| 1243 | if (ret >= 0) { | ||
| 1244 | ret = do_iter_write(file, &iter, pos, flags); | ||
| 1245 | kfree(iov); | ||
| 1246 | } | ||
| 1285 | if (ret > 0) | 1247 | if (ret > 0) |
| 1286 | add_wchar(current, ret); | 1248 | add_wchar(current, ret); |
| 1287 | inc_syscw(current); | 1249 | inc_syscw(current); |
diff --git a/fs/splice.c b/fs/splice.c index 540c4a44756c..ae41201d0325 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -762,7 +762,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 762 | 762 | ||
| 763 | iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n, | 763 | iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n, |
| 764 | sd.total_len - left); | 764 | sd.total_len - left); |
| 765 | ret = vfs_iter_write(out, &from, &sd.pos); | 765 | ret = vfs_iter_write(out, &from, &sd.pos, 0); |
| 766 | if (ret <= 0) | 766 | if (ret <= 0) |
| 767 | break; | 767 | break; |
| 768 | 768 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 9a540d399d1b..818568c8e5ed 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -2819,8 +2819,10 @@ extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); | |||
| 2819 | extern ssize_t generic_file_direct_write(struct kiocb *, struct iov_iter *); | 2819 | extern ssize_t generic_file_direct_write(struct kiocb *, struct iov_iter *); |
| 2820 | extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t); | 2820 | extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t); |
| 2821 | 2821 | ||
| 2822 | ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos); | 2822 | ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos, |
| 2823 | ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos); | 2823 | int flags); |
| 2824 | ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos, | ||
| 2825 | int flags); | ||
| 2824 | 2826 | ||
| 2825 | /* fs/block_dev.c */ | 2827 | /* fs/block_dev.c */ |
| 2826 | extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); | 2828 | extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); |
