diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:26:51 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:26:51 -0400 |
commit | 36e9f6535f398952772df5238b23e795a2810f86 (patch) | |
tree | ee06829309dbe7ff87ed953f6e7dc7433f48cc85 | |
parent | a96114fa1acaabca1091a27aacebd945a5733075 (diff) | |
parent | bc917be8105993c256338ad1189650364a741483 (diff) |
Merge branch 'iov_iter' into for-next
-rw-r--r-- | include/linux/uio.h | 14 | ||||
-rw-r--r-- | lib/iov_iter.c | 57 |
2 files changed, 71 insertions, 0 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h index a69ed25af07f..15f11fb9fff6 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
@@ -140,4 +140,18 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) | |||
140 | size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | 140 | size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
141 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | 141 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
142 | 142 | ||
143 | int import_iovec(int type, const struct iovec __user * uvector, | ||
144 | unsigned nr_segs, unsigned fast_segs, | ||
145 | struct iovec **iov, struct iov_iter *i); | ||
146 | |||
147 | #ifdef CONFIG_COMPAT | ||
148 | struct compat_iovec; | ||
149 | int compat_import_iovec(int type, const struct compat_iovec __user * uvector, | ||
150 | unsigned nr_segs, unsigned fast_segs, | ||
151 | struct iovec **iov, struct iov_iter *i); | ||
152 | #endif | ||
153 | |||
154 | int import_single_range(int type, void __user *buf, size_t len, | ||
155 | struct iovec *iov, struct iov_iter *i); | ||
156 | |||
143 | #endif | 157 | #endif |
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index b80f84376b91..75232ad0a5e7 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -792,3 +792,60 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) | |||
792 | flags); | 792 | flags); |
793 | } | 793 | } |
794 | EXPORT_SYMBOL(dup_iter); | 794 | EXPORT_SYMBOL(dup_iter); |
795 | |||
796 | int import_iovec(int type, const struct iovec __user * uvector, | ||
797 | unsigned nr_segs, unsigned fast_segs, | ||
798 | struct iovec **iov, struct iov_iter *i) | ||
799 | { | ||
800 | ssize_t n; | ||
801 | struct iovec *p; | ||
802 | n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs, | ||
803 | *iov, &p); | ||
804 | if (n < 0) { | ||
805 | if (p != *iov) | ||
806 | kfree(p); | ||
807 | *iov = NULL; | ||
808 | return n; | ||
809 | } | ||
810 | iov_iter_init(i, type, p, nr_segs, n); | ||
811 | *iov = p == *iov ? NULL : p; | ||
812 | return 0; | ||
813 | } | ||
814 | EXPORT_SYMBOL(import_iovec); | ||
815 | |||
816 | #ifdef CONFIG_COMPAT | ||
817 | #include <linux/compat.h> | ||
818 | |||
819 | int compat_import_iovec(int type, const struct compat_iovec __user * uvector, | ||
820 | unsigned nr_segs, unsigned fast_segs, | ||
821 | struct iovec **iov, struct iov_iter *i) | ||
822 | { | ||
823 | ssize_t n; | ||
824 | struct iovec *p; | ||
825 | n = compat_rw_copy_check_uvector(type, uvector, nr_segs, fast_segs, | ||
826 | *iov, &p); | ||
827 | if (n < 0) { | ||
828 | if (p != *iov) | ||
829 | kfree(p); | ||
830 | *iov = NULL; | ||
831 | return n; | ||
832 | } | ||
833 | iov_iter_init(i, type, p, nr_segs, n); | ||
834 | *iov = p == *iov ? NULL : p; | ||
835 | return 0; | ||
836 | } | ||
837 | #endif | ||
838 | |||
839 | int import_single_range(int rw, void __user *buf, size_t len, | ||
840 | struct iovec *iov, struct iov_iter *i) | ||
841 | { | ||
842 | if (len > MAX_RW_COUNT) | ||
843 | len = MAX_RW_COUNT; | ||
844 | if (unlikely(!access_ok(!rw, buf, len))) | ||
845 | return -EFAULT; | ||
846 | |||
847 | iov->iov_base = buf; | ||
848 | iov->iov_len = len; | ||
849 | iov_iter_init(i, rw, iov, 1, len); | ||
850 | return 0; | ||
851 | } | ||