aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2014-06-19 14:22:56 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2014-06-27 14:47:58 -0400
commitac5ccdba3a1659b3517e7e99ef7d35a6a2d77cf4 (patch)
treecbbec5559a3cb50e47c73494a9f256155a284efe
parent97c99b47ac58bacb7c09e1f47d5d184434f6b06a (diff)
iovec: move memcpy_from/toiovecend to lib/iovec.c
ERROR: "memcpy_fromiovecend" [drivers/vhost/vhost_scsi.ko] undefined! commit 9f977ef7b671f6169eca78bf40f230fe84b7c7e5 vhost-scsi: Include prot_bytes into expected data transfer length in target-pending makes drivers/vhost/scsi.c call memcpy_fromiovecend(). This function is not available when CONFIG_NET is not enabled. socket.h already includes uio.h, so no callers need updating. Reported-by: Randy Dunlap <rdunlap@infradead.org> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--include/linux/socket.h4
-rw-r--r--include/linux/uio.h5
-rw-r--r--lib/iovec.c55
-rw-r--r--net/core/iovec.c55
4 files changed, 59 insertions, 60 deletions
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 8e98297f1388..ec538fc287a6 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -305,8 +305,6 @@ struct ucred {
305/* IPX options */ 305/* IPX options */
306#define IPX_TYPE 1 306#define IPX_TYPE 1
307 307
308extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
309 int offset, int len);
310extern int csum_partial_copy_fromiovecend(unsigned char *kdata, 308extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
311 struct iovec *iov, 309 struct iovec *iov,
312 int offset, 310 int offset,
@@ -315,8 +313,6 @@ extern unsigned long iov_pages(const struct iovec *iov, int offset,
315 unsigned long nr_segs); 313 unsigned long nr_segs);
316 314
317extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode); 315extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode);
318extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
319 int offset, int len);
320extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); 316extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
321extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); 317extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
322 318
diff --git a/include/linux/uio.h b/include/linux/uio.h
index e2231e47cec1..04c8c4bb4927 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -111,6 +111,9 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
111 111
112int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); 112int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
113int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); 113int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
114 114int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
115 int offset, int len);
116int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
117 int offset, int len);
115 118
116#endif 119#endif
diff --git a/lib/iovec.c b/lib/iovec.c
index 454baa88bf27..7a7c2da4cddf 100644
--- a/lib/iovec.c
+++ b/lib/iovec.c
@@ -51,3 +51,58 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
51 return 0; 51 return 0;
52} 52}
53EXPORT_SYMBOL(memcpy_toiovec); 53EXPORT_SYMBOL(memcpy_toiovec);
54
55/*
56 * Copy kernel to iovec. Returns -EFAULT on error.
57 */
58
59int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata,
60 int offset, int len)
61{
62 int copy;
63 for (; len > 0; ++iov) {
64 /* Skip over the finished iovecs */
65 if (unlikely(offset >= iov->iov_len)) {
66 offset -= iov->iov_len;
67 continue;
68 }
69 copy = min_t(unsigned int, iov->iov_len - offset, len);
70 if (copy_to_user(iov->iov_base + offset, kdata, copy))
71 return -EFAULT;
72 offset = 0;
73 kdata += copy;
74 len -= copy;
75 }
76
77 return 0;
78}
79EXPORT_SYMBOL(memcpy_toiovecend);
80
81/*
82 * Copy iovec to kernel. Returns -EFAULT on error.
83 */
84
85int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
86 int offset, int len)
87{
88 /* Skip over the finished iovecs */
89 while (offset >= iov->iov_len) {
90 offset -= iov->iov_len;
91 iov++;
92 }
93
94 while (len > 0) {
95 u8 __user *base = iov->iov_base + offset;
96 int copy = min_t(unsigned int, len, iov->iov_len - offset);
97
98 offset = 0;
99 if (copy_from_user(kdata, base, copy))
100 return -EFAULT;
101 len -= copy;
102 kdata += copy;
103 iov++;
104 }
105
106 return 0;
107}
108EXPORT_SYMBOL(memcpy_fromiovecend);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index b61869429f4c..827dd6beb49c 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -75,61 +75,6 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
75} 75}
76 76
77/* 77/*
78 * Copy kernel to iovec. Returns -EFAULT on error.
79 */
80
81int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata,
82 int offset, int len)
83{
84 int copy;
85 for (; len > 0; ++iov) {
86 /* Skip over the finished iovecs */
87 if (unlikely(offset >= iov->iov_len)) {
88 offset -= iov->iov_len;
89 continue;
90 }
91 copy = min_t(unsigned int, iov->iov_len - offset, len);
92 if (copy_to_user(iov->iov_base + offset, kdata, copy))
93 return -EFAULT;
94 offset = 0;
95 kdata += copy;
96 len -= copy;
97 }
98
99 return 0;
100}
101EXPORT_SYMBOL(memcpy_toiovecend);
102
103/*
104 * Copy iovec to kernel. Returns -EFAULT on error.
105 */
106
107int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
108 int offset, int len)
109{
110 /* Skip over the finished iovecs */
111 while (offset >= iov->iov_len) {
112 offset -= iov->iov_len;
113 iov++;
114 }
115
116 while (len > 0) {
117 u8 __user *base = iov->iov_base + offset;
118 int copy = min_t(unsigned int, len, iov->iov_len - offset);
119
120 offset = 0;
121 if (copy_from_user(kdata, base, copy))
122 return -EFAULT;
123 len -= copy;
124 kdata += copy;
125 iov++;
126 }
127
128 return 0;
129}
130EXPORT_SYMBOL(memcpy_fromiovecend);
131
132/*
133 * And now for the all-in-one: copy and checksum from a user iovec 78 * And now for the all-in-one: copy and checksum from a user iovec
134 * directly to a datagram 79 * directly to a datagram
135 * Calls to csum_partial but the last must be in 32 bit chunks 80 * Calls to csum_partial but the last must be in 32 bit chunks