From: Nicholas Bellinger n...@linux-iscsi.org
This patch adds a new memcpy_fromiovec_out() library function which modifies
the passed *iov following memcpy_fromiovec(), but also returns the next current
iovec pointer via **iov_out.
This is useful for vhost ANY_LAYOUT support when guests are allowed to generate
incoming virtio request headers combined with subsequent SGL payloads into a
single iovec.
Cc: Michael S. Tsirkin m...@redhat.com
Cc: Paolo Bonzini pbonz...@redhat.com
Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org
---
include/linux/uio.h | 2 ++
lib/iovec.c | 35 +++
2 files changed, 37 insertions(+)
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 1c5e453..3e4473d 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -136,6 +136,8 @@ size_t csum_and_copy_to_iter(void *addr, size_t bytes,
__wsum *csum, struct iov_
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct
iov_iter *i);
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+int memcpy_fromiovec_out(unsigned char *kdata, struct iovec *iov,
+struct iovec **iov_out, int len);
int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
int offset, int len);
int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
diff --git a/lib/iovec.c b/lib/iovec.c
index 2d99cb4..24c8148 100644
--- a/lib/iovec.c
+++ b/lib/iovec.c
@@ -28,6 +28,41 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec
*iov, int len)
EXPORT_SYMBOL(memcpy_fromiovec);
/*
+ * Copy iovec to kernel, modifying the passed *iov entries.
+ *
+ * Save **iov_out for the caller to use upon return, that may either
+ * contain the current entry with a re-calculated iov_base + iov_len
+ * or next unmodified entry.
+ *
+ * Also note that any iovec entries preceeding the final *iov_out are
+ * zeroed by copy_from_user().
+ *
+ * Returns -EFAULT on error.
+ */
+
+int memcpy_fromiovec_out(unsigned char *kdata, struct iovec *iov,
+struct iovec **iov_out, int len)
+{
+ while (len 0) {
+ if (iov-iov_len) {
+ int copy = min_t(unsigned int, len, iov-iov_len);
+ if (copy_from_user(kdata, iov-iov_base, copy))
+ return -EFAULT;
+ len -= copy;
+ kdata += copy;
+ iov-iov_base += copy;
+ iov-iov_len -= copy;
+ }
+ if (!iov-iov_len)
+ iov++;
+ }
+ *iov_out = iov;
+
+ return 0;
+}
+EXPORT_SYMBOL(memcpy_fromiovec_out);
+
+/*
* Copy kernel to iovec. Returns -EFAULT on error.
*/
--
1.9.1
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html