diff options
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 400fe81c973e..9d1e76bb9ee1 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -731,6 +731,62 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | |||
731 | return ret; | 731 | return ret; |
732 | } | 732 | } |
733 | 733 | ||
734 | static inline loff_t pos_from_hilo(unsigned long high, unsigned long low) | ||
735 | { | ||
736 | #define HALF_LONG_BITS (BITS_PER_LONG / 2) | ||
737 | return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; | ||
738 | } | ||
739 | |||
740 | SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | ||
741 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | ||
742 | { | ||
743 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
744 | struct file *file; | ||
745 | ssize_t ret = -EBADF; | ||
746 | int fput_needed; | ||
747 | |||
748 | if (pos < 0) | ||
749 | return -EINVAL; | ||
750 | |||
751 | file = fget_light(fd, &fput_needed); | ||
752 | if (file) { | ||
753 | ret = -ESPIPE; | ||
754 | if (file->f_mode & FMODE_PREAD) | ||
755 | ret = vfs_readv(file, vec, vlen, &pos); | ||
756 | fput_light(file, fput_needed); | ||
757 | } | ||
758 | |||
759 | if (ret > 0) | ||
760 | add_rchar(current, ret); | ||
761 | inc_syscr(current); | ||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | ||
766 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | ||
767 | { | ||
768 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
769 | struct file *file; | ||
770 | ssize_t ret = -EBADF; | ||
771 | int fput_needed; | ||
772 | |||
773 | if (pos < 0) | ||
774 | return -EINVAL; | ||
775 | |||
776 | file = fget_light(fd, &fput_needed); | ||
777 | if (file) { | ||
778 | ret = -ESPIPE; | ||
779 | if (file->f_mode & FMODE_PWRITE) | ||
780 | ret = vfs_writev(file, vec, vlen, &pos); | ||
781 | fput_light(file, fput_needed); | ||
782 | } | ||
783 | |||
784 | if (ret > 0) | ||
785 | add_wchar(current, ret); | ||
786 | inc_syscw(current); | ||
787 | return ret; | ||
788 | } | ||
789 | |||
734 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | 790 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, |
735 | size_t count, loff_t max) | 791 | size_t count, loff_t max) |
736 | { | 792 | { |