From patchwork Fri May 3 20:29:15 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 2519341 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 2E01A3FE80 for ; Fri, 3 May 2013 20:30:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934305Ab3ECUab (ORCPT ); Fri, 3 May 2013 16:30:31 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:47611 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934308Ab3ECUaT (ORCPT ); Fri, 3 May 2013 16:30:19 -0400 Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by aserp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r43KU8mx003233 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 3 May 2013 20:30:09 GMT Received: from userz7022.oracle.com (userz7022.oracle.com [156.151.31.86]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r43KU7t6023139 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Fri, 3 May 2013 20:30:08 GMT Received: from abhmt114.oracle.com (abhmt114.oracle.com [141.146.116.66]) by userz7022.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r43KU7Yv017801; Fri, 3 May 2013 20:30:07 GMT Received: from lappy.us.oracle.com (/10.159.134.53) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 03 May 2013 13:30:06 -0700 From: Sasha Levin To: penberg@kernel.org, asias@redhat.com Cc: kvm@vger.kernel.org, Sasha Levin Subject: [PATCH 6/8] kvm tools: steal iovec handling routines from the kernel Date: Fri, 3 May 2013 16:29:15 -0400 Message-Id: <1367612957-6719-6-git-send-email-sasha.levin@oracle.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1367612957-6719-1-git-send-email-sasha.levin@oracle.com> References: <1367612957-6719-1-git-send-email-sasha.levin@oracle.com> X-Source-IP: acsinet22.oracle.com [141.146.126.238] Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org They're hidden inside net/core/iovec.c. It'd be nice to just link to that but they're not too generic and come with tons of net/ specific code we don't want. So we just copy over the relevant parts. Signed-off-by: Sasha Levin --- tools/kvm/Makefile | 1 + tools/kvm/include/kvm/iovec.h | 21 +++++++ tools/kvm/include/linux/kernel.h | 10 ++++ tools/kvm/util/iovec.c | 126 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 tools/kvm/include/kvm/iovec.h create mode 100644 tools/kvm/util/iovec.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index a0a0a9b..70accaa 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -86,6 +86,7 @@ OBJS += net/uip/csum.o OBJS += net/uip/dhcp.o OBJS += kvm-cmd.o OBJS += util/init.o +OBJS += util/iovec.o OBJS += util/rbtree.o OBJS += util/threadpool.o OBJS += util/parse-options.o diff --git a/tools/kvm/include/kvm/iovec.h b/tools/kvm/include/kvm/iovec.h new file mode 100644 index 0000000..fe79dd4 --- /dev/null +++ b/tools/kvm/include/kvm/iovec.h @@ -0,0 +1,21 @@ +#ifndef KVM_UTIL_IOVEC_H_ +#define KVM_UTIL_IOVEC_H_ + +extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); +extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + size_t offset, int len); +extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); +extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, + size_t offset, int len); + +static inline size_t iov_size(const struct iovec *iovec, size_t len) +{ + size_t size = 0, i; + + for (i = 0; i < len; i++) + size += iovec[i].iov_len; + + return size; +} + +#endif diff --git a/tools/kvm/include/linux/kernel.h b/tools/kvm/include/linux/kernel.h index 1e9abe9..f2bff5f 100644 --- a/tools/kvm/include/linux/kernel.h +++ b/tools/kvm/include/linux/kernel.h @@ -36,6 +36,16 @@ (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1: __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; }) + #define true 1 #endif diff --git a/tools/kvm/util/iovec.c b/tools/kvm/util/iovec.c new file mode 100644 index 0000000..0c8b9cf --- /dev/null +++ b/tools/kvm/util/iovec.c @@ -0,0 +1,126 @@ +/* + * iovec manipulation routines. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Fixes: + * Andrew Lunn : Errors in iovec copying. + * Pedro Roque : Added memcpy_fromiovecend and + * csum_..._fromiovecend. + * Andi Kleen : fixed error handling for 2.1 + * Alexey Kuznetsov: 2.1 optimisations + * Andi Kleen : Fix csum*fromiovecend for IPv6. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Copy kernel to iovec. Returns -EFAULT on error. + * + * Note: this modifies the original iovec. + */ + +int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) +{ + while (len > 0) { + if (iov->iov_len) { + int copy = min_t(unsigned int, iov->iov_len, len); + memcpy(iov->iov_base, kdata, copy); + kdata += copy; + len -= copy; + iov->iov_len -= copy; + iov->iov_base += copy; + } + iov++; + } + + return 0; +} +EXPORT_SYMBOL(memcpy_toiovec); + +/* + * Copy kernel to iovec. Returns -EFAULT on error. + */ + +int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, + size_t offset, int len) +{ + int copy; + for (; len > 0; ++iov) { + /* Skip over the finished iovecs */ + if (unlikely(offset >= iov->iov_len)) { + offset -= iov->iov_len; + continue; + } + copy = min_t(unsigned int, iov->iov_len - offset, len); + memcpy(iov->iov_base + offset, kdata, copy); + offset = 0; + kdata += copy; + len -= copy; + } + + return 0; +} +EXPORT_SYMBOL(memcpy_toiovecend); + +/* + * Copy iovec to kernel. Returns -EFAULT on error. + * + * Note: this modifies the original iovec. + */ + +int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len) +{ + while (len > 0) { + if (iov->iov_len) { + int copy = min_t(unsigned int, len, iov->iov_len); + memcpy(kdata, iov->iov_base, copy); + len -= copy; + kdata += copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } + iov++; + } + + return 0; +} +EXPORT_SYMBOL(memcpy_fromiovec); + +/* + * Copy iovec from kernel. Returns -EFAULT on error. + */ + +int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + size_t offset, int len) +{ + /* Skip over the finished iovecs */ + while (offset >= iov->iov_len) { + offset -= iov->iov_len; + iov++; + } + + while (len > 0) { + char *base = iov->iov_base + offset; + int copy = min_t(unsigned int, len, iov->iov_len - offset); + + offset = 0; + memcpy(kdata, base, copy); + len -= copy; + kdata += copy; + iov++; + } + + return 0; +} +EXPORT_SYMBOL(memcpy_fromiovecend);