diff options
author | Milosz Tanski <milosz@adfin.com> | 2016-03-03 10:03:59 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-03-04 12:20:10 -0500 |
commit | f17d8b35452cab31a70d224964cd583fb2845449 (patch) | |
tree | 7d34a6b279d7546bb17d417eee80991f648e846c /fs/read_write.c | |
parent | 793b80ef14af56d20c998265287648ad34239b6f (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.c | 161 |
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 | ||
896 | EXPORT_SYMBOL(vfs_writev); | 896 | EXPORT_SYMBOL(vfs_writev); |
897 | 897 | ||
898 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | 898 | static 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 | ||
918 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | 918 | static 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 | ||
944 | SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | 944 | static 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 | ||
968 | SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | 967 | static 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 | ||
990 | SYSCALL_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 | |||
996 | SYSCALL_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 | |||
1002 | SYSCALL_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 | |||
1010 | SYSCALL_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 | |||
1022 | SYSCALL_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 | |||
1030 | SYSCALL_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 | ||
994 | static ssize_t compat_do_readv_writev(int type, struct file *file, | 1044 | static ssize_t compat_do_readv_writev(int type, struct file *file, |
@@ -1046,7 +1096,7 @@ out: | |||
1046 | 1096 | ||
1047 | static size_t compat_readv(struct file *file, | 1097 | static 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 | ||
1062 | out: | 1112 | out: |
1063 | if (ret > 0) | 1113 | if (ret > 0) |
@@ -1066,9 +1116,9 @@ out: | |||
1066 | return ret; | 1116 | return ret; |
1067 | } | 1117 | } |
1068 | 1118 | ||
1069 | COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | 1119 | static 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 | ||
1087 | static long __compat_sys_preadv64(unsigned long fd, | 1138 | COMPAT_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 | |||
1145 | static 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 | |||
1182 | COMPAT_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 | ||
1124 | static size_t compat_writev(struct file *file, | 1195 | static 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 | ||
1146 | COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | 1217 | static 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 | ||
1164 | static long __compat_sys_pwritev64(unsigned long fd, | 1235 | COMPAT_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 | |||
1242 | static 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 | |||
1279 | COMPAT_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 | ||
1202 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | 1293 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, |