diff options
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 176 |
1 files changed, 77 insertions, 99 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 1adfb691e4f1..28b38279a219 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -232,23 +232,18 @@ EXPORT_SYMBOL(vfs_llseek); | |||
232 | SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin) | 232 | SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin) |
233 | { | 233 | { |
234 | off_t retval; | 234 | off_t retval; |
235 | struct file * file; | 235 | struct fd f = fdget(fd); |
236 | int fput_needed; | 236 | if (!f.file) |
237 | 237 | return -EBADF; | |
238 | retval = -EBADF; | ||
239 | file = fget_light(fd, &fput_needed); | ||
240 | if (!file) | ||
241 | goto bad; | ||
242 | 238 | ||
243 | retval = -EINVAL; | 239 | retval = -EINVAL; |
244 | if (origin <= SEEK_MAX) { | 240 | if (origin <= SEEK_MAX) { |
245 | loff_t res = vfs_llseek(file, offset, origin); | 241 | loff_t res = vfs_llseek(f.file, offset, origin); |
246 | retval = res; | 242 | retval = res; |
247 | if (res != (loff_t)retval) | 243 | if (res != (loff_t)retval) |
248 | retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ | 244 | retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ |
249 | } | 245 | } |
250 | fput_light(file, fput_needed); | 246 | fdput(f); |
251 | bad: | ||
252 | return retval; | 247 | return retval; |
253 | } | 248 | } |
254 | 249 | ||
@@ -258,20 +253,17 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, | |||
258 | unsigned int, origin) | 253 | unsigned int, origin) |
259 | { | 254 | { |
260 | int retval; | 255 | int retval; |
261 | struct file * file; | 256 | struct fd f = fdget(fd); |
262 | loff_t offset; | 257 | loff_t offset; |
263 | int fput_needed; | ||
264 | 258 | ||
265 | retval = -EBADF; | 259 | if (!f.file) |
266 | file = fget_light(fd, &fput_needed); | 260 | return -EBADF; |
267 | if (!file) | ||
268 | goto bad; | ||
269 | 261 | ||
270 | retval = -EINVAL; | 262 | retval = -EINVAL; |
271 | if (origin > SEEK_MAX) | 263 | if (origin > SEEK_MAX) |
272 | goto out_putf; | 264 | goto out_putf; |
273 | 265 | ||
274 | offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low, | 266 | offset = vfs_llseek(f.file, ((loff_t) offset_high << 32) | offset_low, |
275 | origin); | 267 | origin); |
276 | 268 | ||
277 | retval = (int)offset; | 269 | retval = (int)offset; |
@@ -281,8 +273,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, | |||
281 | retval = 0; | 273 | retval = 0; |
282 | } | 274 | } |
283 | out_putf: | 275 | out_putf: |
284 | fput_light(file, fput_needed); | 276 | fdput(f); |
285 | bad: | ||
286 | return retval; | 277 | return retval; |
287 | } | 278 | } |
288 | #endif | 279 | #endif |
@@ -461,34 +452,29 @@ static inline void file_pos_write(struct file *file, loff_t pos) | |||
461 | 452 | ||
462 | SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | 453 | SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) |
463 | { | 454 | { |
464 | struct file *file; | 455 | struct fd f = fdget(fd); |
465 | ssize_t ret = -EBADF; | 456 | ssize_t ret = -EBADF; |
466 | int fput_needed; | ||
467 | 457 | ||
468 | file = fget_light(fd, &fput_needed); | 458 | if (f.file) { |
469 | if (file) { | 459 | loff_t pos = file_pos_read(f.file); |
470 | loff_t pos = file_pos_read(file); | 460 | ret = vfs_read(f.file, buf, count, &pos); |
471 | ret = vfs_read(file, buf, count, &pos); | 461 | file_pos_write(f.file, pos); |
472 | file_pos_write(file, pos); | 462 | fdput(f); |
473 | fput_light(file, fput_needed); | ||
474 | } | 463 | } |
475 | |||
476 | return ret; | 464 | return ret; |
477 | } | 465 | } |
478 | 466 | ||
479 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, | 467 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, |
480 | size_t, count) | 468 | size_t, count) |
481 | { | 469 | { |
482 | struct file *file; | 470 | struct fd f = fdget(fd); |
483 | ssize_t ret = -EBADF; | 471 | ssize_t ret = -EBADF; |
484 | int fput_needed; | ||
485 | 472 | ||
486 | file = fget_light(fd, &fput_needed); | 473 | if (f.file) { |
487 | if (file) { | 474 | loff_t pos = file_pos_read(f.file); |
488 | loff_t pos = file_pos_read(file); | 475 | ret = vfs_write(f.file, buf, count, &pos); |
489 | ret = vfs_write(file, buf, count, &pos); | 476 | file_pos_write(f.file, pos); |
490 | file_pos_write(file, pos); | 477 | fdput(f); |
491 | fput_light(file, fput_needed); | ||
492 | } | 478 | } |
493 | 479 | ||
494 | return ret; | 480 | return ret; |
@@ -497,19 +483,18 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, | |||
497 | SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf, | 483 | SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf, |
498 | size_t count, loff_t pos) | 484 | size_t count, loff_t pos) |
499 | { | 485 | { |
500 | struct file *file; | 486 | struct fd f; |
501 | ssize_t ret = -EBADF; | 487 | ssize_t ret = -EBADF; |
502 | int fput_needed; | ||
503 | 488 | ||
504 | if (pos < 0) | 489 | if (pos < 0) |
505 | return -EINVAL; | 490 | return -EINVAL; |
506 | 491 | ||
507 | file = fget_light(fd, &fput_needed); | 492 | f = fdget(fd); |
508 | if (file) { | 493 | if (f.file) { |
509 | ret = -ESPIPE; | 494 | ret = -ESPIPE; |
510 | if (file->f_mode & FMODE_PREAD) | 495 | if (f.file->f_mode & FMODE_PREAD) |
511 | ret = vfs_read(file, buf, count, &pos); | 496 | ret = vfs_read(f.file, buf, count, &pos); |
512 | fput_light(file, fput_needed); | 497 | fdput(f); |
513 | } | 498 | } |
514 | 499 | ||
515 | return ret; | 500 | return ret; |
@@ -526,19 +511,18 @@ SYSCALL_ALIAS(sys_pread64, SyS_pread64); | |||
526 | SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf, | 511 | SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf, |
527 | size_t count, loff_t pos) | 512 | size_t count, loff_t pos) |
528 | { | 513 | { |
529 | struct file *file; | 514 | struct fd f; |
530 | ssize_t ret = -EBADF; | 515 | ssize_t ret = -EBADF; |
531 | int fput_needed; | ||
532 | 516 | ||
533 | if (pos < 0) | 517 | if (pos < 0) |
534 | return -EINVAL; | 518 | return -EINVAL; |
535 | 519 | ||
536 | file = fget_light(fd, &fput_needed); | 520 | f = fdget(fd); |
537 | if (file) { | 521 | if (f.file) { |
538 | ret = -ESPIPE; | 522 | ret = -ESPIPE; |
539 | if (file->f_mode & FMODE_PWRITE) | 523 | if (f.file->f_mode & FMODE_PWRITE) |
540 | ret = vfs_write(file, buf, count, &pos); | 524 | ret = vfs_write(f.file, buf, count, &pos); |
541 | fput_light(file, fput_needed); | 525 | fdput(f); |
542 | } | 526 | } |
543 | 527 | ||
544 | return ret; | 528 | return ret; |
@@ -789,16 +773,14 @@ EXPORT_SYMBOL(vfs_writev); | |||
789 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | 773 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, |
790 | unsigned long, vlen) | 774 | unsigned long, vlen) |
791 | { | 775 | { |
792 | struct file *file; | 776 | struct fd f = fdget(fd); |
793 | ssize_t ret = -EBADF; | 777 | ssize_t ret = -EBADF; |
794 | int fput_needed; | ||
795 | 778 | ||
796 | file = fget_light(fd, &fput_needed); | 779 | if (f.file) { |
797 | if (file) { | 780 | loff_t pos = file_pos_read(f.file); |
798 | loff_t pos = file_pos_read(file); | 781 | ret = vfs_readv(f.file, vec, vlen, &pos); |
799 | ret = vfs_readv(file, vec, vlen, &pos); | 782 | file_pos_write(f.file, pos); |
800 | file_pos_write(file, pos); | 783 | fdput(f); |
801 | fput_light(file, fput_needed); | ||
802 | } | 784 | } |
803 | 785 | ||
804 | if (ret > 0) | 786 | if (ret > 0) |
@@ -810,16 +792,14 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
810 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | 792 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, |
811 | unsigned long, vlen) | 793 | unsigned long, vlen) |
812 | { | 794 | { |
813 | struct file *file; | 795 | struct fd f = fdget(fd); |
814 | ssize_t ret = -EBADF; | 796 | ssize_t ret = -EBADF; |
815 | int fput_needed; | ||
816 | 797 | ||
817 | file = fget_light(fd, &fput_needed); | 798 | if (f.file) { |
818 | if (file) { | 799 | loff_t pos = file_pos_read(f.file); |
819 | loff_t pos = file_pos_read(file); | 800 | ret = vfs_writev(f.file, vec, vlen, &pos); |
820 | ret = vfs_writev(file, vec, vlen, &pos); | 801 | file_pos_write(f.file, pos); |
821 | file_pos_write(file, pos); | 802 | fdput(f); |
822 | fput_light(file, fput_needed); | ||
823 | } | 803 | } |
824 | 804 | ||
825 | if (ret > 0) | 805 | if (ret > 0) |
@@ -838,19 +818,18 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | |||
838 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | 818 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) |
839 | { | 819 | { |
840 | loff_t pos = pos_from_hilo(pos_h, pos_l); | 820 | loff_t pos = pos_from_hilo(pos_h, pos_l); |
841 | struct file *file; | 821 | struct fd f; |
842 | ssize_t ret = -EBADF; | 822 | ssize_t ret = -EBADF; |
843 | int fput_needed; | ||
844 | 823 | ||
845 | if (pos < 0) | 824 | if (pos < 0) |
846 | return -EINVAL; | 825 | return -EINVAL; |
847 | 826 | ||
848 | file = fget_light(fd, &fput_needed); | 827 | f = fdget(fd); |
849 | if (file) { | 828 | if (f.file) { |
850 | ret = -ESPIPE; | 829 | ret = -ESPIPE; |
851 | if (file->f_mode & FMODE_PREAD) | 830 | if (f.file->f_mode & FMODE_PREAD) |
852 | ret = vfs_readv(file, vec, vlen, &pos); | 831 | ret = vfs_readv(f.file, vec, vlen, &pos); |
853 | fput_light(file, fput_needed); | 832 | fdput(f); |
854 | } | 833 | } |
855 | 834 | ||
856 | if (ret > 0) | 835 | if (ret > 0) |
@@ -863,19 +842,18 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
863 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | 842 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) |
864 | { | 843 | { |
865 | loff_t pos = pos_from_hilo(pos_h, pos_l); | 844 | loff_t pos = pos_from_hilo(pos_h, pos_l); |
866 | struct file *file; | 845 | struct fd f; |
867 | ssize_t ret = -EBADF; | 846 | ssize_t ret = -EBADF; |
868 | int fput_needed; | ||
869 | 847 | ||
870 | if (pos < 0) | 848 | if (pos < 0) |
871 | return -EINVAL; | 849 | return -EINVAL; |
872 | 850 | ||
873 | file = fget_light(fd, &fput_needed); | 851 | f = fdget(fd); |
874 | if (file) { | 852 | if (f.file) { |
875 | ret = -ESPIPE; | 853 | ret = -ESPIPE; |
876 | if (file->f_mode & FMODE_PWRITE) | 854 | if (f.file->f_mode & FMODE_PWRITE) |
877 | ret = vfs_writev(file, vec, vlen, &pos); | 855 | ret = vfs_writev(f.file, vec, vlen, &pos); |
878 | fput_light(file, fput_needed); | 856 | fdput(f); |
879 | } | 857 | } |
880 | 858 | ||
881 | if (ret > 0) | 859 | if (ret > 0) |
@@ -887,28 +865,28 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
887 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | 865 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, |
888 | size_t count, loff_t max) | 866 | size_t count, loff_t max) |
889 | { | 867 | { |
890 | struct file * in_file, * out_file; | 868 | struct fd in, out; |
891 | struct inode * in_inode, * out_inode; | 869 | struct inode *in_inode, *out_inode; |
892 | loff_t pos; | 870 | loff_t pos; |
893 | ssize_t retval; | 871 | ssize_t retval; |
894 | int fput_needed_in, fput_needed_out, fl; | 872 | int fl; |
895 | 873 | ||
896 | /* | 874 | /* |
897 | * Get input file, and verify that it is ok.. | 875 | * Get input file, and verify that it is ok.. |
898 | */ | 876 | */ |
899 | retval = -EBADF; | 877 | retval = -EBADF; |
900 | in_file = fget_light(in_fd, &fput_needed_in); | 878 | in = fdget(in_fd); |
901 | if (!in_file) | 879 | if (!in.file) |
902 | goto out; | 880 | goto out; |
903 | if (!(in_file->f_mode & FMODE_READ)) | 881 | if (!(in.file->f_mode & FMODE_READ)) |
904 | goto fput_in; | 882 | goto fput_in; |
905 | retval = -ESPIPE; | 883 | retval = -ESPIPE; |
906 | if (!ppos) | 884 | if (!ppos) |
907 | ppos = &in_file->f_pos; | 885 | ppos = &in.file->f_pos; |
908 | else | 886 | else |
909 | if (!(in_file->f_mode & FMODE_PREAD)) | 887 | if (!(in.file->f_mode & FMODE_PREAD)) |
910 | goto fput_in; | 888 | goto fput_in; |
911 | retval = rw_verify_area(READ, in_file, ppos, count); | 889 | retval = rw_verify_area(READ, in.file, ppos, count); |
912 | if (retval < 0) | 890 | if (retval < 0) |
913 | goto fput_in; | 891 | goto fput_in; |
914 | count = retval; | 892 | count = retval; |
@@ -917,15 +895,15 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
917 | * Get output file, and verify that it is ok.. | 895 | * Get output file, and verify that it is ok.. |
918 | */ | 896 | */ |
919 | retval = -EBADF; | 897 | retval = -EBADF; |
920 | out_file = fget_light(out_fd, &fput_needed_out); | 898 | out = fdget(out_fd); |
921 | if (!out_file) | 899 | if (!out.file) |
922 | goto fput_in; | 900 | goto fput_in; |
923 | if (!(out_file->f_mode & FMODE_WRITE)) | 901 | if (!(out.file->f_mode & FMODE_WRITE)) |
924 | goto fput_out; | 902 | goto fput_out; |
925 | retval = -EINVAL; | 903 | retval = -EINVAL; |
926 | in_inode = in_file->f_path.dentry->d_inode; | 904 | in_inode = in.file->f_path.dentry->d_inode; |
927 | out_inode = out_file->f_path.dentry->d_inode; | 905 | out_inode = out.file->f_path.dentry->d_inode; |
928 | retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); | 906 | retval = rw_verify_area(WRITE, out.file, &out.file->f_pos, count); |
929 | if (retval < 0) | 907 | if (retval < 0) |
930 | goto fput_out; | 908 | goto fput_out; |
931 | count = retval; | 909 | count = retval; |
@@ -949,10 +927,10 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
949 | * and the application is arguably buggy if it doesn't expect | 927 | * and the application is arguably buggy if it doesn't expect |
950 | * EAGAIN on a non-blocking file descriptor. | 928 | * EAGAIN on a non-blocking file descriptor. |
951 | */ | 929 | */ |
952 | if (in_file->f_flags & O_NONBLOCK) | 930 | if (in.file->f_flags & O_NONBLOCK) |
953 | fl = SPLICE_F_NONBLOCK; | 931 | fl = SPLICE_F_NONBLOCK; |
954 | #endif | 932 | #endif |
955 | retval = do_splice_direct(in_file, ppos, out_file, count, fl); | 933 | retval = do_splice_direct(in.file, ppos, out.file, count, fl); |
956 | 934 | ||
957 | if (retval > 0) { | 935 | if (retval > 0) { |
958 | add_rchar(current, retval); | 936 | add_rchar(current, retval); |
@@ -965,9 +943,9 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
965 | retval = -EOVERFLOW; | 943 | retval = -EOVERFLOW; |
966 | 944 | ||
967 | fput_out: | 945 | fput_out: |
968 | fput_light(out_file, fput_needed_out); | 946 | fdput(out); |
969 | fput_in: | 947 | fput_in: |
970 | fput_light(in_file, fput_needed_in); | 948 | fdput(in); |
971 | out: | 949 | out: |
972 | return retval; | 950 | return retval; |
973 | } | 951 | } |