diff options
author | Christoph Hellwig <hch@lst.de> | 2016-03-03 10:03:58 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-03-04 12:20:10 -0500 |
commit | 793b80ef14af56d20c998265287648ad34239b6f (patch) | |
tree | 930a6879d16b435829f10b36566bf80df64850cc /fs/read_write.c | |
parent | 92e963f50fc74041b5e9e744c330dca48e04f08d (diff) |
vfs: pass a flags argument to vfs_readv/vfs_writev
This way we can set kiocb flags also from the sync read/write path for
the read_iter/write_iter operations. For now there is no way to pass
flags to plain read/write operations as there is no real need for that,
and all flags passed are explicitly rejected for these files.
Signed-off-by: Milosz Tanski <milosz@adfin.com>
[hch: rebased on top of my kiocb changes]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Stephen Bates <stephen.bates@pmcs.com>
Tested-by: Stephen Bates <stephen.bates@pmcs.com>
Acked-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 324ec271cc4e..7d453c3e1cb6 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -692,11 +692,14 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) | |||
692 | EXPORT_SYMBOL(iov_shorten); | 692 | EXPORT_SYMBOL(iov_shorten); |
693 | 693 | ||
694 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | 694 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, |
695 | loff_t *ppos, iter_fn_t fn) | 695 | loff_t *ppos, iter_fn_t fn, int flags) |
696 | { | 696 | { |
697 | struct kiocb kiocb; | 697 | struct kiocb kiocb; |
698 | ssize_t ret; | 698 | ssize_t ret; |
699 | 699 | ||
700 | if (flags) | ||
701 | return -EOPNOTSUPP; | ||
702 | |||
700 | init_sync_kiocb(&kiocb, filp); | 703 | init_sync_kiocb(&kiocb, filp); |
701 | kiocb.ki_pos = *ppos; | 704 | kiocb.ki_pos = *ppos; |
702 | 705 | ||
@@ -708,10 +711,13 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | |||
708 | 711 | ||
709 | /* Do it by hand, with file-ops */ | 712 | /* Do it by hand, with file-ops */ |
710 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, | 713 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, |
711 | loff_t *ppos, io_fn_t fn) | 714 | loff_t *ppos, io_fn_t fn, int flags) |
712 | { | 715 | { |
713 | ssize_t ret = 0; | 716 | ssize_t ret = 0; |
714 | 717 | ||
718 | if (flags) | ||
719 | return -EOPNOTSUPP; | ||
720 | |||
715 | while (iov_iter_count(iter)) { | 721 | while (iov_iter_count(iter)) { |
716 | struct iovec iovec = iov_iter_iovec(iter); | 722 | struct iovec iovec = iov_iter_iovec(iter); |
717 | ssize_t nr; | 723 | ssize_t nr; |
@@ -812,7 +818,8 @@ out: | |||
812 | 818 | ||
813 | static ssize_t do_readv_writev(int type, struct file *file, | 819 | static ssize_t do_readv_writev(int type, struct file *file, |
814 | const struct iovec __user * uvector, | 820 | const struct iovec __user * uvector, |
815 | unsigned long nr_segs, loff_t *pos) | 821 | unsigned long nr_segs, loff_t *pos, |
822 | int flags) | ||
816 | { | 823 | { |
817 | size_t tot_len; | 824 | size_t tot_len; |
818 | struct iovec iovstack[UIO_FASTIOV]; | 825 | struct iovec iovstack[UIO_FASTIOV]; |
@@ -844,9 +851,9 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
844 | } | 851 | } |
845 | 852 | ||
846 | if (iter_fn) | 853 | if (iter_fn) |
847 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn); | 854 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); |
848 | else | 855 | else |
849 | ret = do_loop_readv_writev(file, &iter, pos, fn); | 856 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); |
850 | 857 | ||
851 | if (type != READ) | 858 | if (type != READ) |
852 | file_end_write(file); | 859 | file_end_write(file); |
@@ -863,27 +870,27 @@ out: | |||
863 | } | 870 | } |
864 | 871 | ||
865 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, | 872 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, |
866 | unsigned long vlen, loff_t *pos) | 873 | unsigned long vlen, loff_t *pos, int flags) |
867 | { | 874 | { |
868 | if (!(file->f_mode & FMODE_READ)) | 875 | if (!(file->f_mode & FMODE_READ)) |
869 | return -EBADF; | 876 | return -EBADF; |
870 | if (!(file->f_mode & FMODE_CAN_READ)) | 877 | if (!(file->f_mode & FMODE_CAN_READ)) |
871 | return -EINVAL; | 878 | return -EINVAL; |
872 | 879 | ||
873 | return do_readv_writev(READ, file, vec, vlen, pos); | 880 | return do_readv_writev(READ, file, vec, vlen, pos, flags); |
874 | } | 881 | } |
875 | 882 | ||
876 | EXPORT_SYMBOL(vfs_readv); | 883 | EXPORT_SYMBOL(vfs_readv); |
877 | 884 | ||
878 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, | 885 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, |
879 | unsigned long vlen, loff_t *pos) | 886 | unsigned long vlen, loff_t *pos, int flags) |
880 | { | 887 | { |
881 | if (!(file->f_mode & FMODE_WRITE)) | 888 | if (!(file->f_mode & FMODE_WRITE)) |
882 | return -EBADF; | 889 | return -EBADF; |
883 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 890 | if (!(file->f_mode & FMODE_CAN_WRITE)) |
884 | return -EINVAL; | 891 | return -EINVAL; |
885 | 892 | ||
886 | return do_readv_writev(WRITE, file, vec, vlen, pos); | 893 | return do_readv_writev(WRITE, file, vec, vlen, pos, flags); |
887 | } | 894 | } |
888 | 895 | ||
889 | EXPORT_SYMBOL(vfs_writev); | 896 | EXPORT_SYMBOL(vfs_writev); |
@@ -896,7 +903,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
896 | 903 | ||
897 | if (f.file) { | 904 | if (f.file) { |
898 | loff_t pos = file_pos_read(f.file); | 905 | loff_t pos = file_pos_read(f.file); |
899 | ret = vfs_readv(f.file, vec, vlen, &pos); | 906 | ret = vfs_readv(f.file, vec, vlen, &pos, 0); |
900 | if (ret >= 0) | 907 | if (ret >= 0) |
901 | file_pos_write(f.file, pos); | 908 | file_pos_write(f.file, pos); |
902 | fdput_pos(f); | 909 | fdput_pos(f); |
@@ -916,7 +923,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | |||
916 | 923 | ||
917 | if (f.file) { | 924 | if (f.file) { |
918 | loff_t pos = file_pos_read(f.file); | 925 | loff_t pos = file_pos_read(f.file); |
919 | ret = vfs_writev(f.file, vec, vlen, &pos); | 926 | ret = vfs_writev(f.file, vec, vlen, &pos, 0); |
920 | if (ret >= 0) | 927 | if (ret >= 0) |
921 | file_pos_write(f.file, pos); | 928 | file_pos_write(f.file, pos); |
922 | fdput_pos(f); | 929 | fdput_pos(f); |
@@ -948,7 +955,7 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | |||
948 | if (f.file) { | 955 | if (f.file) { |
949 | ret = -ESPIPE; | 956 | ret = -ESPIPE; |
950 | if (f.file->f_mode & FMODE_PREAD) | 957 | if (f.file->f_mode & FMODE_PREAD) |
951 | ret = vfs_readv(f.file, vec, vlen, &pos); | 958 | ret = vfs_readv(f.file, vec, vlen, &pos, 0); |
952 | fdput(f); | 959 | fdput(f); |
953 | } | 960 | } |
954 | 961 | ||
@@ -972,7 +979,7 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
972 | if (f.file) { | 979 | if (f.file) { |
973 | ret = -ESPIPE; | 980 | ret = -ESPIPE; |
974 | if (f.file->f_mode & FMODE_PWRITE) | 981 | if (f.file->f_mode & FMODE_PWRITE) |
975 | ret = vfs_writev(f.file, vec, vlen, &pos); | 982 | ret = vfs_writev(f.file, vec, vlen, &pos, 0); |
976 | fdput(f); | 983 | fdput(f); |
977 | } | 984 | } |
978 | 985 | ||
@@ -986,7 +993,8 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
986 | 993 | ||
987 | static ssize_t compat_do_readv_writev(int type, struct file *file, | 994 | static ssize_t compat_do_readv_writev(int type, struct file *file, |
988 | const struct compat_iovec __user *uvector, | 995 | const struct compat_iovec __user *uvector, |
989 | unsigned long nr_segs, loff_t *pos) | 996 | unsigned long nr_segs, loff_t *pos, |
997 | int flags) | ||
990 | { | 998 | { |
991 | compat_ssize_t tot_len; | 999 | compat_ssize_t tot_len; |
992 | struct iovec iovstack[UIO_FASTIOV]; | 1000 | struct iovec iovstack[UIO_FASTIOV]; |
@@ -1018,9 +1026,9 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
1018 | } | 1026 | } |
1019 | 1027 | ||
1020 | if (iter_fn) | 1028 | if (iter_fn) |
1021 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn); | 1029 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); |
1022 | else | 1030 | else |
1023 | ret = do_loop_readv_writev(file, &iter, pos, fn); | 1031 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); |
1024 | 1032 | ||
1025 | if (type != READ) | 1033 | if (type != READ) |
1026 | file_end_write(file); | 1034 | file_end_write(file); |
@@ -1049,7 +1057,7 @@ static size_t compat_readv(struct file *file, | |||
1049 | if (!(file->f_mode & FMODE_CAN_READ)) | 1057 | if (!(file->f_mode & FMODE_CAN_READ)) |
1050 | goto out; | 1058 | goto out; |
1051 | 1059 | ||
1052 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos); | 1060 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos, 0); |
1053 | 1061 | ||
1054 | out: | 1062 | out: |
1055 | if (ret > 0) | 1063 | if (ret > 0) |
@@ -1126,7 +1134,7 @@ static size_t compat_writev(struct file *file, | |||
1126 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 1134 | if (!(file->f_mode & FMODE_CAN_WRITE)) |
1127 | goto out; | 1135 | goto out; |
1128 | 1136 | ||
1129 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); | 1137 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, 0); |
1130 | 1138 | ||
1131 | out: | 1139 | out: |
1132 | if (ret > 0) | 1140 | if (ret > 0) |