Message ID | 1422849994-3419-2-git-send-email-nab@daterainc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Feb 02, 2015 at 04:06:24AM +0000, Nicholas A. Bellinger wrote: > From: Nicholas Bellinger <nab@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. Please, don't. Just use copy_from_iter(); you are open-coding an uglier variant of such. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Feb 02, 2015 at 04:44:12AM +0000, Al Viro wrote: > On Mon, Feb 02, 2015 at 04:06:24AM +0000, Nicholas A. Bellinger wrote: > > From: Nicholas Bellinger <nab@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. > > Please, don't. Just use copy_from_iter(); you are open-coding an uglier > variant of such. PS: see vfs.git#for-davem (or postings on netdev with the same stuff). I really hope to bury memcpy_...iovec...() crap for good; please, don't reintroduce more of it. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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. */