aboutsummaryrefslogtreecommitdiffstats
path: root/fs/read_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/read_write.c')
-rw-r--r--fs/read_write.c100
1 files changed, 64 insertions, 36 deletions
diff --git a/fs/read_write.c b/fs/read_write.c
index 58e440df1bc6..31c6efa43183 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -264,10 +264,22 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
264} 264}
265EXPORT_SYMBOL(vfs_llseek); 265EXPORT_SYMBOL(vfs_llseek);
266 266
267static inline struct fd fdget_pos(int fd)
268{
269 return __to_fd(__fdget_pos(fd));
270}
271
272static inline void fdput_pos(struct fd f)
273{
274 if (f.flags & FDPUT_POS_UNLOCK)
275 mutex_unlock(&f.file->f_pos_lock);
276 fdput(f);
277}
278
267SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) 279SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
268{ 280{
269 off_t retval; 281 off_t retval;
270 struct fd f = fdget(fd); 282 struct fd f = fdget_pos(fd);
271 if (!f.file) 283 if (!f.file)
272 return -EBADF; 284 return -EBADF;
273 285
@@ -278,7 +290,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
278 if (res != (loff_t)retval) 290 if (res != (loff_t)retval)
279 retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ 291 retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
280 } 292 }
281 fdput(f); 293 fdput_pos(f);
282 return retval; 294 return retval;
283} 295}
284 296
@@ -295,7 +307,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
295 unsigned int, whence) 307 unsigned int, whence)
296{ 308{
297 int retval; 309 int retval;
298 struct fd f = fdget(fd); 310 struct fd f = fdget_pos(fd);
299 loff_t offset; 311 loff_t offset;
300 312
301 if (!f.file) 313 if (!f.file)
@@ -315,7 +327,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
315 retval = 0; 327 retval = 0;
316 } 328 }
317out_putf: 329out_putf:
318 fdput(f); 330 fdput_pos(f);
319 return retval; 331 return retval;
320} 332}
321#endif 333#endif
@@ -498,7 +510,7 @@ static inline void file_pos_write(struct file *file, loff_t pos)
498 510
499SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) 511SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
500{ 512{
501 struct fd f = fdget(fd); 513 struct fd f = fdget_pos(fd);
502 ssize_t ret = -EBADF; 514 ssize_t ret = -EBADF;
503 515
504 if (f.file) { 516 if (f.file) {
@@ -506,7 +518,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
506 ret = vfs_read(f.file, buf, count, &pos); 518 ret = vfs_read(f.file, buf, count, &pos);
507 if (ret >= 0) 519 if (ret >= 0)
508 file_pos_write(f.file, pos); 520 file_pos_write(f.file, pos);
509 fdput(f); 521 fdput_pos(f);
510 } 522 }
511 return ret; 523 return ret;
512} 524}
@@ -514,7 +526,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
514SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, 526SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
515 size_t, count) 527 size_t, count)
516{ 528{
517 struct fd f = fdget(fd); 529 struct fd f = fdget_pos(fd);
518 ssize_t ret = -EBADF; 530 ssize_t ret = -EBADF;
519 531
520 if (f.file) { 532 if (f.file) {
@@ -522,7 +534,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
522 ret = vfs_write(f.file, buf, count, &pos); 534 ret = vfs_write(f.file, buf, count, &pos);
523 if (ret >= 0) 535 if (ret >= 0)
524 file_pos_write(f.file, pos); 536 file_pos_write(f.file, pos);
525 fdput(f); 537 fdput_pos(f);
526 } 538 }
527 539
528 return ret; 540 return ret;
@@ -797,7 +809,7 @@ EXPORT_SYMBOL(vfs_writev);
797SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, 809SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
798 unsigned long, vlen) 810 unsigned long, vlen)
799{ 811{
800 struct fd f = fdget(fd); 812 struct fd f = fdget_pos(fd);
801 ssize_t ret = -EBADF; 813 ssize_t ret = -EBADF;
802 814
803 if (f.file) { 815 if (f.file) {
@@ -805,7 +817,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
805 ret = vfs_readv(f.file, vec, vlen, &pos); 817 ret = vfs_readv(f.file, vec, vlen, &pos);
806 if (ret >= 0) 818 if (ret >= 0)
807 file_pos_write(f.file, pos); 819 file_pos_write(f.file, pos);
808 fdput(f); 820 fdput_pos(f);
809 } 821 }
810 822
811 if (ret > 0) 823 if (ret > 0)
@@ -817,7 +829,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
817SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, 829SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
818 unsigned long, vlen) 830 unsigned long, vlen)
819{ 831{
820 struct fd f = fdget(fd); 832 struct fd f = fdget_pos(fd);
821 ssize_t ret = -EBADF; 833 ssize_t ret = -EBADF;
822 834
823 if (f.file) { 835 if (f.file) {
@@ -825,7 +837,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
825 ret = vfs_writev(f.file, vec, vlen, &pos); 837 ret = vfs_writev(f.file, vec, vlen, &pos);
826 if (ret >= 0) 838 if (ret >= 0)
827 file_pos_write(f.file, pos); 839 file_pos_write(f.file, pos);
828 fdput(f); 840 fdput_pos(f);
829 } 841 }
830 842
831 if (ret > 0) 843 if (ret > 0)
@@ -901,10 +913,6 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
901 io_fn_t fn; 913 io_fn_t fn;
902 iov_fn_t fnv; 914 iov_fn_t fnv;
903 915
904 ret = -EFAULT;
905 if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
906 goto out;
907
908 ret = compat_rw_copy_check_uvector(type, uvector, nr_segs, 916 ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
909 UIO_FASTIOV, iovstack, &iov); 917 UIO_FASTIOV, iovstack, &iov);
910 if (ret <= 0) 918 if (ret <= 0)
@@ -968,11 +976,11 @@ out:
968 return ret; 976 return ret;
969} 977}
970 978
971COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd, 979COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
972 const struct compat_iovec __user *,vec, 980 const struct compat_iovec __user *,vec,
973 unsigned long, vlen) 981 compat_ulong_t, vlen)
974{ 982{
975 struct fd f = fdget(fd); 983 struct fd f = fdget_pos(fd);
976 ssize_t ret; 984 ssize_t ret;
977 loff_t pos; 985 loff_t pos;
978 986
@@ -982,13 +990,13 @@ COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
982 ret = compat_readv(f.file, vec, vlen, &pos); 990 ret = compat_readv(f.file, vec, vlen, &pos);
983 if (ret >= 0) 991 if (ret >= 0)
984 f.file->f_pos = pos; 992 f.file->f_pos = pos;
985 fdput(f); 993 fdput_pos(f);
986 return ret; 994 return ret;
987} 995}
988 996
989COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd, 997static long __compat_sys_preadv64(unsigned long fd,
990 const struct compat_iovec __user *,vec, 998 const struct compat_iovec __user *vec,
991 unsigned long, vlen, loff_t, pos) 999 unsigned long vlen, loff_t pos)
992{ 1000{
993 struct fd f; 1001 struct fd f;
994 ssize_t ret; 1002 ssize_t ret;
@@ -1005,12 +1013,22 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
1005 return ret; 1013 return ret;
1006} 1014}
1007 1015
1008COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd, 1016#ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
1017COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
1009 const struct compat_iovec __user *,vec, 1018 const struct compat_iovec __user *,vec,
1010 unsigned long, vlen, u32, pos_low, u32, pos_high) 1019 unsigned long, vlen, loff_t, pos)
1020{
1021 return __compat_sys_preadv64(fd, vec, vlen, pos);
1022}
1023#endif
1024
1025COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
1026 const struct compat_iovec __user *,vec,
1027 compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
1011{ 1028{
1012 loff_t pos = ((loff_t)pos_high << 32) | pos_low; 1029 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1013 return compat_sys_preadv64(fd, vec, vlen, pos); 1030
1031 return __compat_sys_preadv64(fd, vec, vlen, pos);
1014} 1032}
1015 1033
1016static size_t compat_writev(struct file *file, 1034static size_t compat_writev(struct file *file,
@@ -1035,11 +1053,11 @@ out:
1035 return ret; 1053 return ret;
1036} 1054}
1037 1055
1038COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd, 1056COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
1039 const struct compat_iovec __user *, vec, 1057 const struct compat_iovec __user *, vec,
1040 unsigned long, vlen) 1058 compat_ulong_t, vlen)
1041{ 1059{
1042 struct fd f = fdget(fd); 1060 struct fd f = fdget_pos(fd);
1043 ssize_t ret; 1061 ssize_t ret;
1044 loff_t pos; 1062 loff_t pos;
1045 1063
@@ -1049,13 +1067,13 @@ COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
1049 ret = compat_writev(f.file, vec, vlen, &pos); 1067 ret = compat_writev(f.file, vec, vlen, &pos);
1050 if (ret >= 0) 1068 if (ret >= 0)
1051 f.file->f_pos = pos; 1069 f.file->f_pos = pos;
1052 fdput(f); 1070 fdput_pos(f);
1053 return ret; 1071 return ret;
1054} 1072}
1055 1073
1056COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd, 1074static long __compat_sys_pwritev64(unsigned long fd,
1057 const struct compat_iovec __user *,vec, 1075 const struct compat_iovec __user *vec,
1058 unsigned long, vlen, loff_t, pos) 1076 unsigned long vlen, loff_t pos)
1059{ 1077{
1060 struct fd f; 1078 struct fd f;
1061 ssize_t ret; 1079 ssize_t ret;
@@ -1072,12 +1090,22 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
1072 return ret; 1090 return ret;
1073} 1091}
1074 1092
1075COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd, 1093#ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
1094COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
1095 const struct compat_iovec __user *,vec,
1096 unsigned long, vlen, loff_t, pos)
1097{
1098 return __compat_sys_pwritev64(fd, vec, vlen, pos);
1099}
1100#endif
1101
1102COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
1076 const struct compat_iovec __user *,vec, 1103 const struct compat_iovec __user *,vec,
1077 unsigned long, vlen, u32, pos_low, u32, pos_high) 1104 compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
1078{ 1105{
1079 loff_t pos = ((loff_t)pos_high << 32) | pos_low; 1106 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1080 return compat_sys_pwritev64(fd, vec, vlen, pos); 1107
1108 return __compat_sys_pwritev64(fd, vec, vlen, pos);
1081} 1109}
1082#endif 1110#endif
1083 1111