summaryrefslogtreecommitdiffstats
path: root/fs/read_write.c
diff options
context:
space:
mode:
authorMilosz Tanski <milosz@adfin.com>2016-03-03 10:03:59 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2016-03-04 12:20:10 -0500
commitf17d8b35452cab31a70d224964cd583fb2845449 (patch)
tree7d34a6b279d7546bb17d417eee80991f648e846c /fs/read_write.c
parent793b80ef14af56d20c998265287648ad34239b6f (diff)
vfs: vfs: Define new syscalls preadv2,pwritev2
New syscalls that take an flag argument. No flags are added yet in this patch. 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.c161
1 files changed, 126 insertions, 35 deletions
diff --git a/fs/read_write.c b/fs/read_write.c
index 7d453c3e1cb6..e9c9e2a667ce 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -895,15 +895,15 @@ ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
895 895
896EXPORT_SYMBOL(vfs_writev); 896EXPORT_SYMBOL(vfs_writev);
897 897
898SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, 898static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
899 unsigned long, vlen) 899 unsigned long vlen, int flags)
900{ 900{
901 struct fd f = fdget_pos(fd); 901 struct fd f = fdget_pos(fd);
902 ssize_t ret = -EBADF; 902 ssize_t ret = -EBADF;
903 903
904 if (f.file) { 904 if (f.file) {
905 loff_t pos = file_pos_read(f.file); 905 loff_t pos = file_pos_read(f.file);
906 ret = vfs_readv(f.file, vec, vlen, &pos, 0); 906 ret = vfs_readv(f.file, vec, vlen, &pos, flags);
907 if (ret >= 0) 907 if (ret >= 0)
908 file_pos_write(f.file, pos); 908 file_pos_write(f.file, pos);
909 fdput_pos(f); 909 fdput_pos(f);
@@ -915,15 +915,15 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
915 return ret; 915 return ret;
916} 916}
917 917
918SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, 918static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
919 unsigned long, vlen) 919 unsigned long vlen, int flags)
920{ 920{
921 struct fd f = fdget_pos(fd); 921 struct fd f = fdget_pos(fd);
922 ssize_t ret = -EBADF; 922 ssize_t ret = -EBADF;
923 923
924 if (f.file) { 924 if (f.file) {
925 loff_t pos = file_pos_read(f.file); 925 loff_t pos = file_pos_read(f.file);
926 ret = vfs_writev(f.file, vec, vlen, &pos, 0); 926 ret = vfs_writev(f.file, vec, vlen, &pos, flags);
927 if (ret >= 0) 927 if (ret >= 0)
928 file_pos_write(f.file, pos); 928 file_pos_write(f.file, pos);
929 fdput_pos(f); 929 fdput_pos(f);
@@ -941,10 +941,9 @@ static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
941 return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; 941 return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
942} 942}
943 943
944SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, 944static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
945 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) 945 unsigned long vlen, loff_t pos, int flags)
946{ 946{
947 loff_t pos = pos_from_hilo(pos_h, pos_l);
948 struct fd f; 947 struct fd f;
949 ssize_t ret = -EBADF; 948 ssize_t ret = -EBADF;
950 949
@@ -955,7 +954,7 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
955 if (f.file) { 954 if (f.file) {
956 ret = -ESPIPE; 955 ret = -ESPIPE;
957 if (f.file->f_mode & FMODE_PREAD) 956 if (f.file->f_mode & FMODE_PREAD)
958 ret = vfs_readv(f.file, vec, vlen, &pos, 0); 957 ret = vfs_readv(f.file, vec, vlen, &pos, flags);
959 fdput(f); 958 fdput(f);
960 } 959 }
961 960
@@ -965,10 +964,9 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
965 return ret; 964 return ret;
966} 965}
967 966
968SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, 967static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
969 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) 968 unsigned long vlen, loff_t pos, int flags)
970{ 969{
971 loff_t pos = pos_from_hilo(pos_h, pos_l);
972 struct fd f; 970 struct fd f;
973 ssize_t ret = -EBADF; 971 ssize_t ret = -EBADF;
974 972
@@ -979,7 +977,7 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
979 if (f.file) { 977 if (f.file) {
980 ret = -ESPIPE; 978 ret = -ESPIPE;
981 if (f.file->f_mode & FMODE_PWRITE) 979 if (f.file->f_mode & FMODE_PWRITE)
982 ret = vfs_writev(f.file, vec, vlen, &pos, 0); 980 ret = vfs_writev(f.file, vec, vlen, &pos, flags);
983 fdput(f); 981 fdput(f);
984 } 982 }
985 983
@@ -989,6 +987,58 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
989 return ret; 987 return ret;
990} 988}
991 989
990SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
991 unsigned long, vlen)
992{
993 return do_readv(fd, vec, vlen, 0);
994}
995
996SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
997 unsigned long, vlen)
998{
999 return do_writev(fd, vec, vlen, 0);
1000}
1001
1002SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
1003 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
1004{
1005 loff_t pos = pos_from_hilo(pos_h, pos_l);
1006
1007 return do_preadv(fd, vec, vlen, pos, 0);
1008}
1009
1010SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec,
1011 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
1012 int, flags)
1013{
1014 loff_t pos = pos_from_hilo(pos_h, pos_l);
1015
1016 if (pos == -1)
1017 return do_readv(fd, vec, vlen, flags);
1018
1019 return do_preadv(fd, vec, vlen, pos, flags);
1020}
1021
1022SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
1023 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
1024{
1025 loff_t pos = pos_from_hilo(pos_h, pos_l);
1026
1027 return do_pwritev(fd, vec, vlen, pos, 0);
1028}
1029
1030SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec,
1031 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
1032 int, flags)
1033{
1034 loff_t pos = pos_from_hilo(pos_h, pos_l);
1035
1036 if (pos == -1)
1037 return do_writev(fd, vec, vlen, flags);
1038
1039 return do_pwritev(fd, vec, vlen, pos, flags);
1040}
1041
992#ifdef CONFIG_COMPAT 1042#ifdef CONFIG_COMPAT
993 1043
994static ssize_t compat_do_readv_writev(int type, struct file *file, 1044static ssize_t compat_do_readv_writev(int type, struct file *file,
@@ -1046,7 +1096,7 @@ out:
1046 1096
1047static size_t compat_readv(struct file *file, 1097static size_t compat_readv(struct file *file,
1048 const struct compat_iovec __user *vec, 1098 const struct compat_iovec __user *vec,
1049 unsigned long vlen, loff_t *pos) 1099 unsigned long vlen, loff_t *pos, int flags)
1050{ 1100{
1051 ssize_t ret = -EBADF; 1101 ssize_t ret = -EBADF;
1052 1102
@@ -1057,7 +1107,7 @@ static size_t compat_readv(struct file *file,
1057 if (!(file->f_mode & FMODE_CAN_READ)) 1107 if (!(file->f_mode & FMODE_CAN_READ))
1058 goto out; 1108 goto out;
1059 1109
1060 ret = compat_do_readv_writev(READ, file, vec, vlen, pos, 0); 1110 ret = compat_do_readv_writev(READ, file, vec, vlen, pos, flags);
1061 1111
1062out: 1112out:
1063 if (ret > 0) 1113 if (ret > 0)
@@ -1066,9 +1116,9 @@ out:
1066 return ret; 1116 return ret;
1067} 1117}
1068 1118
1069COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, 1119static size_t do_compat_readv(compat_ulong_t fd,
1070 const struct compat_iovec __user *,vec, 1120 const struct compat_iovec __user *vec,
1071 compat_ulong_t, vlen) 1121 compat_ulong_t vlen, int flags)
1072{ 1122{
1073 struct fd f = fdget_pos(fd); 1123 struct fd f = fdget_pos(fd);
1074 ssize_t ret; 1124 ssize_t ret;
@@ -1077,16 +1127,24 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
1077 if (!f.file) 1127 if (!f.file)
1078 return -EBADF; 1128 return -EBADF;
1079 pos = f.file->f_pos; 1129 pos = f.file->f_pos;
1080 ret = compat_readv(f.file, vec, vlen, &pos); 1130 ret = compat_readv(f.file, vec, vlen, &pos, flags);
1081 if (ret >= 0) 1131 if (ret >= 0)
1082 f.file->f_pos = pos; 1132 f.file->f_pos = pos;
1083 fdput_pos(f); 1133 fdput_pos(f);
1084 return ret; 1134 return ret;
1135
1085} 1136}
1086 1137
1087static long __compat_sys_preadv64(unsigned long fd, 1138COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
1139 const struct compat_iovec __user *,vec,
1140 compat_ulong_t, vlen)
1141{
1142 return do_compat_readv(fd, vec, vlen, 0);
1143}
1144
1145static long do_compat_preadv64(unsigned long fd,
1088 const struct compat_iovec __user *vec, 1146 const struct compat_iovec __user *vec,
1089 unsigned long vlen, loff_t pos) 1147 unsigned long vlen, loff_t pos, int flags)
1090{ 1148{
1091 struct fd f; 1149 struct fd f;
1092 ssize_t ret; 1150 ssize_t ret;
@@ -1098,7 +1156,7 @@ static long __compat_sys_preadv64(unsigned long fd,
1098 return -EBADF; 1156 return -EBADF;
1099 ret = -ESPIPE; 1157 ret = -ESPIPE;
1100 if (f.file->f_mode & FMODE_PREAD) 1158 if (f.file->f_mode & FMODE_PREAD)
1101 ret = compat_readv(f.file, vec, vlen, &pos); 1159 ret = compat_readv(f.file, vec, vlen, &pos, flags);
1102 fdput(f); 1160 fdput(f);
1103 return ret; 1161 return ret;
1104} 1162}
@@ -1108,7 +1166,7 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
1108 const struct compat_iovec __user *,vec, 1166 const struct compat_iovec __user *,vec,
1109 unsigned long, vlen, loff_t, pos) 1167 unsigned long, vlen, loff_t, pos)
1110{ 1168{
1111 return __compat_sys_preadv64(fd, vec, vlen, pos); 1169 return do_compat_preadv64(fd, vec, vlen, pos, 0);
1112} 1170}
1113#endif 1171#endif
1114 1172
@@ -1118,12 +1176,25 @@ COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
1118{ 1176{
1119 loff_t pos = ((loff_t)pos_high << 32) | pos_low; 1177 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1120 1178
1121 return __compat_sys_preadv64(fd, vec, vlen, pos); 1179 return do_compat_preadv64(fd, vec, vlen, pos, 0);
1180}
1181
1182COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd,
1183 const struct compat_iovec __user *,vec,
1184 compat_ulong_t, vlen, u32, pos_low, u32, pos_high,
1185 int, flags)
1186{
1187 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1188
1189 if (pos == -1)
1190 return do_compat_readv(fd, vec, vlen, flags);
1191
1192 return do_compat_preadv64(fd, vec, vlen, pos, flags);
1122} 1193}
1123 1194
1124static size_t compat_writev(struct file *file, 1195static size_t compat_writev(struct file *file,
1125 const struct compat_iovec __user *vec, 1196 const struct compat_iovec __user *vec,
1126 unsigned long vlen, loff_t *pos) 1197 unsigned long vlen, loff_t *pos, int flags)
1127{ 1198{
1128 ssize_t ret = -EBADF; 1199 ssize_t ret = -EBADF;
1129 1200
@@ -1143,9 +1214,9 @@ out:
1143 return ret; 1214 return ret;
1144} 1215}
1145 1216
1146COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, 1217static size_t do_compat_writev(compat_ulong_t fd,
1147 const struct compat_iovec __user *, vec, 1218 const struct compat_iovec __user* vec,
1148 compat_ulong_t, vlen) 1219 compat_ulong_t vlen, int flags)
1149{ 1220{
1150 struct fd f = fdget_pos(fd); 1221 struct fd f = fdget_pos(fd);
1151 ssize_t ret; 1222 ssize_t ret;
@@ -1154,16 +1225,23 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
1154 if (!f.file) 1225 if (!f.file)
1155 return -EBADF; 1226 return -EBADF;
1156 pos = f.file->f_pos; 1227 pos = f.file->f_pos;
1157 ret = compat_writev(f.file, vec, vlen, &pos); 1228 ret = compat_writev(f.file, vec, vlen, &pos, flags);
1158 if (ret >= 0) 1229 if (ret >= 0)
1159 f.file->f_pos = pos; 1230 f.file->f_pos = pos;
1160 fdput_pos(f); 1231 fdput_pos(f);
1161 return ret; 1232 return ret;
1162} 1233}
1163 1234
1164static long __compat_sys_pwritev64(unsigned long fd, 1235COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
1236 const struct compat_iovec __user *, vec,
1237 compat_ulong_t, vlen)
1238{
1239 return do_compat_writev(fd, vec, vlen, 0);
1240}
1241
1242static long do_compat_pwritev64(unsigned long fd,
1165 const struct compat_iovec __user *vec, 1243 const struct compat_iovec __user *vec,
1166 unsigned long vlen, loff_t pos) 1244 unsigned long vlen, loff_t pos, int flags)
1167{ 1245{
1168 struct fd f; 1246 struct fd f;
1169 ssize_t ret; 1247 ssize_t ret;
@@ -1175,7 +1253,7 @@ static long __compat_sys_pwritev64(unsigned long fd,
1175 return -EBADF; 1253 return -EBADF;
1176 ret = -ESPIPE; 1254 ret = -ESPIPE;
1177 if (f.file->f_mode & FMODE_PWRITE) 1255 if (f.file->f_mode & FMODE_PWRITE)
1178 ret = compat_writev(f.file, vec, vlen, &pos); 1256 ret = compat_writev(f.file, vec, vlen, &pos, flags);
1179 fdput(f); 1257 fdput(f);
1180 return ret; 1258 return ret;
1181} 1259}
@@ -1185,7 +1263,7 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
1185 const struct compat_iovec __user *,vec, 1263 const struct compat_iovec __user *,vec,
1186 unsigned long, vlen, loff_t, pos) 1264 unsigned long, vlen, loff_t, pos)
1187{ 1265{
1188 return __compat_sys_pwritev64(fd, vec, vlen, pos); 1266 return do_compat_pwritev64(fd, vec, vlen, pos, 0);
1189} 1267}
1190#endif 1268#endif
1191 1269
@@ -1195,8 +1273,21 @@ COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
1195{ 1273{
1196 loff_t pos = ((loff_t)pos_high << 32) | pos_low; 1274 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1197 1275
1198 return __compat_sys_pwritev64(fd, vec, vlen, pos); 1276 return do_compat_pwritev64(fd, vec, vlen, pos, 0);
1277}
1278
1279COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
1280 const struct compat_iovec __user *,vec,
1281 compat_ulong_t, vlen, u32, pos_low, u32, pos_high, int, flags)
1282{
1283 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1284
1285 if (pos == -1)
1286 return do_compat_writev(fd, vec, vlen, flags);
1287
1288 return do_compat_pwritev64(fd, vec, vlen, pos, flags);
1199} 1289}
1290
1200#endif 1291#endif
1201 1292
1202static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, 1293static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,