diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2014-06-19 14:22:56 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-06-27 14:47:58 -0400 |
commit | ac5ccdba3a1659b3517e7e99ef7d35a6a2d77cf4 (patch) | |
tree | cbbec5559a3cb50e47c73494a9f256155a284efe | |
parent | 97c99b47ac58bacb7c09e1f47d5d184434f6b06a (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.h | 4 | ||||
-rw-r--r-- | include/linux/uio.h | 5 | ||||
-rw-r--r-- | lib/iovec.c | 55 | ||||
-rw-r--r-- | net/core/iovec.c | 55 |
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 | ||
308 | extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, | ||
309 | int offset, int len); | ||
310 | extern int csum_partial_copy_fromiovecend(unsigned char *kdata, | 308 | extern 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 | ||
317 | extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode); | 315 | extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode); |
318 | extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, | ||
319 | int offset, int len); | ||
320 | extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); | 316 | extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); |
321 | extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); | 317 | extern 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 | ||
112 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); | 112 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); |
113 | int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); | 113 | int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); |
114 | 114 | int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, | |
115 | int offset, int len); | ||
116 | int 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 | } |
53 | EXPORT_SYMBOL(memcpy_toiovec); | 53 | EXPORT_SYMBOL(memcpy_toiovec); |
54 | |||
55 | /* | ||
56 | * Copy kernel to iovec. Returns -EFAULT on error. | ||
57 | */ | ||
58 | |||
59 | int 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 | } | ||
79 | EXPORT_SYMBOL(memcpy_toiovecend); | ||
80 | |||
81 | /* | ||
82 | * Copy iovec to kernel. Returns -EFAULT on error. | ||
83 | */ | ||
84 | |||
85 | int 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 | } | ||
108 | EXPORT_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 | |||
81 | int 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 | } | ||
101 | EXPORT_SYMBOL(memcpy_toiovecend); | ||
102 | |||
103 | /* | ||
104 | * Copy iovec to kernel. Returns -EFAULT on error. | ||
105 | */ | ||
106 | |||
107 | int 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 | } | ||
130 | EXPORT_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 |