aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:26:51 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:26:51 -0400
commit36e9f6535f398952772df5238b23e795a2810f86 (patch)
treeee06829309dbe7ff87ed953f6e7dc7433f48cc85
parenta96114fa1acaabca1091a27aacebd945a5733075 (diff)
parentbc917be8105993c256338ad1189650364a741483 (diff)
Merge branch 'iov_iter' into for-next
-rw-r--r--include/linux/uio.h14
-rw-r--r--lib/iov_iter.c57
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)
140size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); 140size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
141size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); 141size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
142 142
143int 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
148struct compat_iovec;
149int 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
154int 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}
794EXPORT_SYMBOL(dup_iter); 794EXPORT_SYMBOL(dup_iter);
795
796int 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}
814EXPORT_SYMBOL(import_iovec);
815
816#ifdef CONFIG_COMPAT
817#include <linux/compat.h>
818
819int 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
839int 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}