diff options
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 197 |
1 files changed, 149 insertions, 48 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index dadf24e5c95b..cf377cf9dfe3 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -693,12 +693,17 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) | |||
693 | EXPORT_SYMBOL(iov_shorten); | 693 | EXPORT_SYMBOL(iov_shorten); |
694 | 694 | ||
695 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | 695 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, |
696 | loff_t *ppos, iter_fn_t fn) | 696 | loff_t *ppos, iter_fn_t fn, int flags) |
697 | { | 697 | { |
698 | struct kiocb kiocb; | 698 | struct kiocb kiocb; |
699 | ssize_t ret; | 699 | ssize_t ret; |
700 | 700 | ||
701 | if (flags & ~RWF_HIPRI) | ||
702 | return -EOPNOTSUPP; | ||
703 | |||
701 | init_sync_kiocb(&kiocb, filp); | 704 | init_sync_kiocb(&kiocb, filp); |
705 | if (flags & RWF_HIPRI) | ||
706 | kiocb.ki_flags |= IOCB_HIPRI; | ||
702 | kiocb.ki_pos = *ppos; | 707 | kiocb.ki_pos = *ppos; |
703 | 708 | ||
704 | ret = fn(&kiocb, iter); | 709 | ret = fn(&kiocb, iter); |
@@ -709,10 +714,13 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | |||
709 | 714 | ||
710 | /* Do it by hand, with file-ops */ | 715 | /* Do it by hand, with file-ops */ |
711 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, | 716 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, |
712 | loff_t *ppos, io_fn_t fn) | 717 | loff_t *ppos, io_fn_t fn, int flags) |
713 | { | 718 | { |
714 | ssize_t ret = 0; | 719 | ssize_t ret = 0; |
715 | 720 | ||
721 | if (flags & ~RWF_HIPRI) | ||
722 | return -EOPNOTSUPP; | ||
723 | |||
716 | while (iov_iter_count(iter)) { | 724 | while (iov_iter_count(iter)) { |
717 | struct iovec iovec = iov_iter_iovec(iter); | 725 | struct iovec iovec = iov_iter_iovec(iter); |
718 | ssize_t nr; | 726 | ssize_t nr; |
@@ -813,7 +821,8 @@ out: | |||
813 | 821 | ||
814 | static ssize_t do_readv_writev(int type, struct file *file, | 822 | static ssize_t do_readv_writev(int type, struct file *file, |
815 | const struct iovec __user * uvector, | 823 | const struct iovec __user * uvector, |
816 | unsigned long nr_segs, loff_t *pos) | 824 | unsigned long nr_segs, loff_t *pos, |
825 | int flags) | ||
817 | { | 826 | { |
818 | size_t tot_len; | 827 | size_t tot_len; |
819 | struct iovec iovstack[UIO_FASTIOV]; | 828 | struct iovec iovstack[UIO_FASTIOV]; |
@@ -845,9 +854,9 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
845 | } | 854 | } |
846 | 855 | ||
847 | if (iter_fn) | 856 | if (iter_fn) |
848 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn); | 857 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); |
849 | else | 858 | else |
850 | ret = do_loop_readv_writev(file, &iter, pos, fn); | 859 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); |
851 | 860 | ||
852 | if (type != READ) | 861 | if (type != READ) |
853 | file_end_write(file); | 862 | file_end_write(file); |
@@ -864,40 +873,40 @@ out: | |||
864 | } | 873 | } |
865 | 874 | ||
866 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, | 875 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, |
867 | unsigned long vlen, loff_t *pos) | 876 | unsigned long vlen, loff_t *pos, int flags) |
868 | { | 877 | { |
869 | if (!(file->f_mode & FMODE_READ)) | 878 | if (!(file->f_mode & FMODE_READ)) |
870 | return -EBADF; | 879 | return -EBADF; |
871 | if (!(file->f_mode & FMODE_CAN_READ)) | 880 | if (!(file->f_mode & FMODE_CAN_READ)) |
872 | return -EINVAL; | 881 | return -EINVAL; |
873 | 882 | ||
874 | return do_readv_writev(READ, file, vec, vlen, pos); | 883 | return do_readv_writev(READ, file, vec, vlen, pos, flags); |
875 | } | 884 | } |
876 | 885 | ||
877 | EXPORT_SYMBOL(vfs_readv); | 886 | EXPORT_SYMBOL(vfs_readv); |
878 | 887 | ||
879 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, | 888 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, |
880 | unsigned long vlen, loff_t *pos) | 889 | unsigned long vlen, loff_t *pos, int flags) |
881 | { | 890 | { |
882 | if (!(file->f_mode & FMODE_WRITE)) | 891 | if (!(file->f_mode & FMODE_WRITE)) |
883 | return -EBADF; | 892 | return -EBADF; |
884 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 893 | if (!(file->f_mode & FMODE_CAN_WRITE)) |
885 | return -EINVAL; | 894 | return -EINVAL; |
886 | 895 | ||
887 | return do_readv_writev(WRITE, file, vec, vlen, pos); | 896 | return do_readv_writev(WRITE, file, vec, vlen, pos, flags); |
888 | } | 897 | } |
889 | 898 | ||
890 | EXPORT_SYMBOL(vfs_writev); | 899 | EXPORT_SYMBOL(vfs_writev); |
891 | 900 | ||
892 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | 901 | static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec, |
893 | unsigned long, vlen) | 902 | unsigned long vlen, int flags) |
894 | { | 903 | { |
895 | struct fd f = fdget_pos(fd); | 904 | struct fd f = fdget_pos(fd); |
896 | ssize_t ret = -EBADF; | 905 | ssize_t ret = -EBADF; |
897 | 906 | ||
898 | if (f.file) { | 907 | if (f.file) { |
899 | loff_t pos = file_pos_read(f.file); | 908 | loff_t pos = file_pos_read(f.file); |
900 | ret = vfs_readv(f.file, vec, vlen, &pos); | 909 | ret = vfs_readv(f.file, vec, vlen, &pos, flags); |
901 | if (ret >= 0) | 910 | if (ret >= 0) |
902 | file_pos_write(f.file, pos); | 911 | file_pos_write(f.file, pos); |
903 | fdput_pos(f); | 912 | fdput_pos(f); |
@@ -909,15 +918,15 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
909 | return ret; | 918 | return ret; |
910 | } | 919 | } |
911 | 920 | ||
912 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | 921 | static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec, |
913 | unsigned long, vlen) | 922 | unsigned long vlen, int flags) |
914 | { | 923 | { |
915 | struct fd f = fdget_pos(fd); | 924 | struct fd f = fdget_pos(fd); |
916 | ssize_t ret = -EBADF; | 925 | ssize_t ret = -EBADF; |
917 | 926 | ||
918 | if (f.file) { | 927 | if (f.file) { |
919 | loff_t pos = file_pos_read(f.file); | 928 | loff_t pos = file_pos_read(f.file); |
920 | ret = vfs_writev(f.file, vec, vlen, &pos); | 929 | ret = vfs_writev(f.file, vec, vlen, &pos, flags); |
921 | if (ret >= 0) | 930 | if (ret >= 0) |
922 | file_pos_write(f.file, pos); | 931 | file_pos_write(f.file, pos); |
923 | fdput_pos(f); | 932 | fdput_pos(f); |
@@ -935,10 +944,9 @@ static inline loff_t pos_from_hilo(unsigned long high, unsigned long low) | |||
935 | return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; | 944 | return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; |
936 | } | 945 | } |
937 | 946 | ||
938 | SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | 947 | static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec, |
939 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | 948 | unsigned long vlen, loff_t pos, int flags) |
940 | { | 949 | { |
941 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
942 | struct fd f; | 950 | struct fd f; |
943 | ssize_t ret = -EBADF; | 951 | ssize_t ret = -EBADF; |
944 | 952 | ||
@@ -949,7 +957,7 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | |||
949 | if (f.file) { | 957 | if (f.file) { |
950 | ret = -ESPIPE; | 958 | ret = -ESPIPE; |
951 | if (f.file->f_mode & FMODE_PREAD) | 959 | if (f.file->f_mode & FMODE_PREAD) |
952 | ret = vfs_readv(f.file, vec, vlen, &pos); | 960 | ret = vfs_readv(f.file, vec, vlen, &pos, flags); |
953 | fdput(f); | 961 | fdput(f); |
954 | } | 962 | } |
955 | 963 | ||
@@ -959,10 +967,9 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | |||
959 | return ret; | 967 | return ret; |
960 | } | 968 | } |
961 | 969 | ||
962 | SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | 970 | static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec, |
963 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | 971 | unsigned long vlen, loff_t pos, int flags) |
964 | { | 972 | { |
965 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
966 | struct fd f; | 973 | struct fd f; |
967 | ssize_t ret = -EBADF; | 974 | ssize_t ret = -EBADF; |
968 | 975 | ||
@@ -973,7 +980,7 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
973 | if (f.file) { | 980 | if (f.file) { |
974 | ret = -ESPIPE; | 981 | ret = -ESPIPE; |
975 | if (f.file->f_mode & FMODE_PWRITE) | 982 | if (f.file->f_mode & FMODE_PWRITE) |
976 | ret = vfs_writev(f.file, vec, vlen, &pos); | 983 | ret = vfs_writev(f.file, vec, vlen, &pos, flags); |
977 | fdput(f); | 984 | fdput(f); |
978 | } | 985 | } |
979 | 986 | ||
@@ -983,11 +990,64 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
983 | return ret; | 990 | return ret; |
984 | } | 991 | } |
985 | 992 | ||
993 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | ||
994 | unsigned long, vlen) | ||
995 | { | ||
996 | return do_readv(fd, vec, vlen, 0); | ||
997 | } | ||
998 | |||
999 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | ||
1000 | unsigned long, vlen) | ||
1001 | { | ||
1002 | return do_writev(fd, vec, vlen, 0); | ||
1003 | } | ||
1004 | |||
1005 | SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | ||
1006 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | ||
1007 | { | ||
1008 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1009 | |||
1010 | return do_preadv(fd, vec, vlen, pos, 0); | ||
1011 | } | ||
1012 | |||
1013 | SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec, | ||
1014 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h, | ||
1015 | int, flags) | ||
1016 | { | ||
1017 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1018 | |||
1019 | if (pos == -1) | ||
1020 | return do_readv(fd, vec, vlen, flags); | ||
1021 | |||
1022 | return do_preadv(fd, vec, vlen, pos, flags); | ||
1023 | } | ||
1024 | |||
1025 | SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | ||
1026 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | ||
1027 | { | ||
1028 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1029 | |||
1030 | return do_pwritev(fd, vec, vlen, pos, 0); | ||
1031 | } | ||
1032 | |||
1033 | SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec, | ||
1034 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h, | ||
1035 | int, flags) | ||
1036 | { | ||
1037 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1038 | |||
1039 | if (pos == -1) | ||
1040 | return do_writev(fd, vec, vlen, flags); | ||
1041 | |||
1042 | return do_pwritev(fd, vec, vlen, pos, flags); | ||
1043 | } | ||
1044 | |||
986 | #ifdef CONFIG_COMPAT | 1045 | #ifdef CONFIG_COMPAT |
987 | 1046 | ||
988 | static ssize_t compat_do_readv_writev(int type, struct file *file, | 1047 | static ssize_t compat_do_readv_writev(int type, struct file *file, |
989 | const struct compat_iovec __user *uvector, | 1048 | const struct compat_iovec __user *uvector, |
990 | unsigned long nr_segs, loff_t *pos) | 1049 | unsigned long nr_segs, loff_t *pos, |
1050 | int flags) | ||
991 | { | 1051 | { |
992 | compat_ssize_t tot_len; | 1052 | compat_ssize_t tot_len; |
993 | struct iovec iovstack[UIO_FASTIOV]; | 1053 | struct iovec iovstack[UIO_FASTIOV]; |
@@ -1019,9 +1079,9 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
1019 | } | 1079 | } |
1020 | 1080 | ||
1021 | if (iter_fn) | 1081 | if (iter_fn) |
1022 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn); | 1082 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); |
1023 | else | 1083 | else |
1024 | ret = do_loop_readv_writev(file, &iter, pos, fn); | 1084 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); |
1025 | 1085 | ||
1026 | if (type != READ) | 1086 | if (type != READ) |
1027 | file_end_write(file); | 1087 | file_end_write(file); |
@@ -1039,7 +1099,7 @@ out: | |||
1039 | 1099 | ||
1040 | static size_t compat_readv(struct file *file, | 1100 | static size_t compat_readv(struct file *file, |
1041 | const struct compat_iovec __user *vec, | 1101 | const struct compat_iovec __user *vec, |
1042 | unsigned long vlen, loff_t *pos) | 1102 | unsigned long vlen, loff_t *pos, int flags) |
1043 | { | 1103 | { |
1044 | ssize_t ret = -EBADF; | 1104 | ssize_t ret = -EBADF; |
1045 | 1105 | ||
@@ -1050,7 +1110,7 @@ static size_t compat_readv(struct file *file, | |||
1050 | if (!(file->f_mode & FMODE_CAN_READ)) | 1110 | if (!(file->f_mode & FMODE_CAN_READ)) |
1051 | goto out; | 1111 | goto out; |
1052 | 1112 | ||
1053 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos); | 1113 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos, flags); |
1054 | 1114 | ||
1055 | out: | 1115 | out: |
1056 | if (ret > 0) | 1116 | if (ret > 0) |
@@ -1059,9 +1119,9 @@ out: | |||
1059 | return ret; | 1119 | return ret; |
1060 | } | 1120 | } |
1061 | 1121 | ||
1062 | COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | 1122 | static size_t do_compat_readv(compat_ulong_t fd, |
1063 | const struct compat_iovec __user *,vec, | 1123 | const struct compat_iovec __user *vec, |
1064 | compat_ulong_t, vlen) | 1124 | compat_ulong_t vlen, int flags) |
1065 | { | 1125 | { |
1066 | struct fd f = fdget_pos(fd); | 1126 | struct fd f = fdget_pos(fd); |
1067 | ssize_t ret; | 1127 | ssize_t ret; |
@@ -1070,16 +1130,24 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | |||
1070 | if (!f.file) | 1130 | if (!f.file) |
1071 | return -EBADF; | 1131 | return -EBADF; |
1072 | pos = f.file->f_pos; | 1132 | pos = f.file->f_pos; |
1073 | ret = compat_readv(f.file, vec, vlen, &pos); | 1133 | ret = compat_readv(f.file, vec, vlen, &pos, flags); |
1074 | if (ret >= 0) | 1134 | if (ret >= 0) |
1075 | f.file->f_pos = pos; | 1135 | f.file->f_pos = pos; |
1076 | fdput_pos(f); | 1136 | fdput_pos(f); |
1077 | return ret; | 1137 | return ret; |
1138 | |||
1139 | } | ||
1140 | |||
1141 | COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | ||
1142 | const struct compat_iovec __user *,vec, | ||
1143 | compat_ulong_t, vlen) | ||
1144 | { | ||
1145 | return do_compat_readv(fd, vec, vlen, 0); | ||
1078 | } | 1146 | } |
1079 | 1147 | ||
1080 | static long __compat_sys_preadv64(unsigned long fd, | 1148 | static long do_compat_preadv64(unsigned long fd, |
1081 | const struct compat_iovec __user *vec, | 1149 | const struct compat_iovec __user *vec, |
1082 | unsigned long vlen, loff_t pos) | 1150 | unsigned long vlen, loff_t pos, int flags) |
1083 | { | 1151 | { |
1084 | struct fd f; | 1152 | struct fd f; |
1085 | ssize_t ret; | 1153 | ssize_t ret; |
@@ -1091,7 +1159,7 @@ static long __compat_sys_preadv64(unsigned long fd, | |||
1091 | return -EBADF; | 1159 | return -EBADF; |
1092 | ret = -ESPIPE; | 1160 | ret = -ESPIPE; |
1093 | if (f.file->f_mode & FMODE_PREAD) | 1161 | if (f.file->f_mode & FMODE_PREAD) |
1094 | ret = compat_readv(f.file, vec, vlen, &pos); | 1162 | ret = compat_readv(f.file, vec, vlen, &pos, flags); |
1095 | fdput(f); | 1163 | fdput(f); |
1096 | return ret; | 1164 | return ret; |
1097 | } | 1165 | } |
@@ -1101,7 +1169,7 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd, | |||
1101 | const struct compat_iovec __user *,vec, | 1169 | const struct compat_iovec __user *,vec, |
1102 | unsigned long, vlen, loff_t, pos) | 1170 | unsigned long, vlen, loff_t, pos) |
1103 | { | 1171 | { |
1104 | return __compat_sys_preadv64(fd, vec, vlen, pos); | 1172 | return do_compat_preadv64(fd, vec, vlen, pos, 0); |
1105 | } | 1173 | } |
1106 | #endif | 1174 | #endif |
1107 | 1175 | ||
@@ -1111,12 +1179,25 @@ COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd, | |||
1111 | { | 1179 | { |
1112 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | 1180 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; |
1113 | 1181 | ||
1114 | return __compat_sys_preadv64(fd, vec, vlen, pos); | 1182 | return do_compat_preadv64(fd, vec, vlen, pos, 0); |
1183 | } | ||
1184 | |||
1185 | COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd, | ||
1186 | const struct compat_iovec __user *,vec, | ||
1187 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high, | ||
1188 | int, flags) | ||
1189 | { | ||
1190 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1191 | |||
1192 | if (pos == -1) | ||
1193 | return do_compat_readv(fd, vec, vlen, flags); | ||
1194 | |||
1195 | return do_compat_preadv64(fd, vec, vlen, pos, flags); | ||
1115 | } | 1196 | } |
1116 | 1197 | ||
1117 | static size_t compat_writev(struct file *file, | 1198 | static size_t compat_writev(struct file *file, |
1118 | const struct compat_iovec __user *vec, | 1199 | const struct compat_iovec __user *vec, |
1119 | unsigned long vlen, loff_t *pos) | 1200 | unsigned long vlen, loff_t *pos, int flags) |
1120 | { | 1201 | { |
1121 | ssize_t ret = -EBADF; | 1202 | ssize_t ret = -EBADF; |
1122 | 1203 | ||
@@ -1127,7 +1208,7 @@ static size_t compat_writev(struct file *file, | |||
1127 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 1208 | if (!(file->f_mode & FMODE_CAN_WRITE)) |
1128 | goto out; | 1209 | goto out; |
1129 | 1210 | ||
1130 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); | 1211 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, 0); |
1131 | 1212 | ||
1132 | out: | 1213 | out: |
1133 | if (ret > 0) | 1214 | if (ret > 0) |
@@ -1136,9 +1217,9 @@ out: | |||
1136 | return ret; | 1217 | return ret; |
1137 | } | 1218 | } |
1138 | 1219 | ||
1139 | COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | 1220 | static size_t do_compat_writev(compat_ulong_t fd, |
1140 | const struct compat_iovec __user *, vec, | 1221 | const struct compat_iovec __user* vec, |
1141 | compat_ulong_t, vlen) | 1222 | compat_ulong_t vlen, int flags) |
1142 | { | 1223 | { |
1143 | struct fd f = fdget_pos(fd); | 1224 | struct fd f = fdget_pos(fd); |
1144 | ssize_t ret; | 1225 | ssize_t ret; |
@@ -1147,16 +1228,23 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | |||
1147 | if (!f.file) | 1228 | if (!f.file) |
1148 | return -EBADF; | 1229 | return -EBADF; |
1149 | pos = f.file->f_pos; | 1230 | pos = f.file->f_pos; |
1150 | ret = compat_writev(f.file, vec, vlen, &pos); | 1231 | ret = compat_writev(f.file, vec, vlen, &pos, flags); |
1151 | if (ret >= 0) | 1232 | if (ret >= 0) |
1152 | f.file->f_pos = pos; | 1233 | f.file->f_pos = pos; |
1153 | fdput_pos(f); | 1234 | fdput_pos(f); |
1154 | return ret; | 1235 | return ret; |
1155 | } | 1236 | } |
1156 | 1237 | ||
1157 | static long __compat_sys_pwritev64(unsigned long fd, | 1238 | COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, |
1239 | const struct compat_iovec __user *, vec, | ||
1240 | compat_ulong_t, vlen) | ||
1241 | { | ||
1242 | return do_compat_writev(fd, vec, vlen, 0); | ||
1243 | } | ||
1244 | |||
1245 | static long do_compat_pwritev64(unsigned long fd, | ||
1158 | const struct compat_iovec __user *vec, | 1246 | const struct compat_iovec __user *vec, |
1159 | unsigned long vlen, loff_t pos) | 1247 | unsigned long vlen, loff_t pos, int flags) |
1160 | { | 1248 | { |
1161 | struct fd f; | 1249 | struct fd f; |
1162 | ssize_t ret; | 1250 | ssize_t ret; |
@@ -1168,7 +1256,7 @@ static long __compat_sys_pwritev64(unsigned long fd, | |||
1168 | return -EBADF; | 1256 | return -EBADF; |
1169 | ret = -ESPIPE; | 1257 | ret = -ESPIPE; |
1170 | if (f.file->f_mode & FMODE_PWRITE) | 1258 | if (f.file->f_mode & FMODE_PWRITE) |
1171 | ret = compat_writev(f.file, vec, vlen, &pos); | 1259 | ret = compat_writev(f.file, vec, vlen, &pos, flags); |
1172 | fdput(f); | 1260 | fdput(f); |
1173 | return ret; | 1261 | return ret; |
1174 | } | 1262 | } |
@@ -1178,7 +1266,7 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd, | |||
1178 | const struct compat_iovec __user *,vec, | 1266 | const struct compat_iovec __user *,vec, |
1179 | unsigned long, vlen, loff_t, pos) | 1267 | unsigned long, vlen, loff_t, pos) |
1180 | { | 1268 | { |
1181 | return __compat_sys_pwritev64(fd, vec, vlen, pos); | 1269 | return do_compat_pwritev64(fd, vec, vlen, pos, 0); |
1182 | } | 1270 | } |
1183 | #endif | 1271 | #endif |
1184 | 1272 | ||
@@ -1188,8 +1276,21 @@ COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd, | |||
1188 | { | 1276 | { |
1189 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | 1277 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; |
1190 | 1278 | ||
1191 | return __compat_sys_pwritev64(fd, vec, vlen, pos); | 1279 | return do_compat_pwritev64(fd, vec, vlen, pos, 0); |
1280 | } | ||
1281 | |||
1282 | COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd, | ||
1283 | const struct compat_iovec __user *,vec, | ||
1284 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high, int, flags) | ||
1285 | { | ||
1286 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1287 | |||
1288 | if (pos == -1) | ||
1289 | return do_compat_writev(fd, vec, vlen, flags); | ||
1290 | |||
1291 | return do_compat_pwritev64(fd, vec, vlen, pos, flags); | ||
1192 | } | 1292 | } |
1293 | |||
1193 | #endif | 1294 | #endif |
1194 | 1295 | ||
1195 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | 1296 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, |