[PATCH-v2 01/11] lib/iovec: Add memcpy_fromiovec_out library function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

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 <mst@xxxxxxxxxx>
Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux