From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LQKyP-0006SX-Nz for qemu-devel@nongnu.org; Fri, 23 Jan 2009 07:17:21 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LQKyP-0006S0-37 for qemu-devel@nongnu.org; Fri, 23 Jan 2009 07:17:21 -0500 Received: from [199.232.76.173] (port=34292 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LQKyO-0006Rx-VO for qemu-devel@nongnu.org; Fri, 23 Jan 2009 07:17:21 -0500 Received: from mx2.redhat.com ([66.187.237.31]:58208) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LQKyO-0005nm-Cs for qemu-devel@nongnu.org; Fri, 23 Jan 2009 07:17:20 -0500 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n0NCHJXA012420 for ; Fri, 23 Jan 2009 07:17:19 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n0NCHKF8023806 for ; Fri, 23 Jan 2009 07:17:20 -0500 Received: from zweiblum.travel.kraxel.org (vpn-10-167.str.redhat.com [10.32.10.167]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n0NCHI43007245 for ; Fri, 23 Jan 2009 07:17:19 -0500 Message-ID: <4979B54C.7090009@redhat.com> Date: Fri, 23 Jan 2009 13:17:16 +0100 From: Gerd Hoffmann MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------000604030103090505070809" Subject: [Qemu-devel] [RfC / experimental patch] preadv/pwritev code for qemu Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------000604030103090505070809 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hi, You needs also the kernel patches if you wanna play with this on linux. On *BSD it should detect preadv being present and use it. No code uses this (yet). cheers, Gerd --------------000604030103090505070809 Content-Type: text/plain; name="0003-preadv-writev-code-for-qemu.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="0003-preadv-writev-code-for-qemu.patch" >>From 8b640cab61853efa622e17bb9145fe242fffc5a4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 22 Jan 2009 16:22:41 +0100 Subject: [PATCH 3/3] preadv/writev code for qemu. Signed-off-by: Gerd Hoffmann --- Makefile | 1 + configure | 13 +++++ qemu-common.h | 3 + qemu-io-syscalls.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 0 deletions(-) create mode 100644 qemu-io-syscalls.c diff --git a/Makefile b/Makefile index a09d6e0..d61f914 100644 --- a/Makefile +++ b/Makefile @@ -85,6 +85,7 @@ OBJS+=sd.o ssi-sd.o OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o +OBJS+=qemu-io-syscalls.o ifdef CONFIG_BRLAPI OBJS+= baum.o diff --git a/configure b/configure index 6a1432a..3cd0e62 100755 --- a/configure +++ b/configure @@ -1027,6 +1027,16 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then fi ########################################## +# preadv probe +cat > $TMPC < /dev/null 2> /dev/null ; then + preadv=yes +fi + +########################################## # fdt probe if test "$fdt" = "yes" ; then fdt=no @@ -1422,6 +1432,9 @@ fi if test "$iovec" = "yes" ; then echo "#define HAVE_IOVEC 1" >> $config_h fi +if test "$preadv" = "yes" ; then + echo "#define HAVE_PREADV 1" >> $config_h +fi if test "$fdt" = "yes" ; then echo "#define HAVE_FDT 1" >> $config_h echo "FDT_LIBS=-lfdt" >> $config_mak diff --git a/qemu-common.h b/qemu-common.h index 42d5e49..0dfc575 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -204,6 +204,9 @@ void qemu_iovec_destroy(QEMUIOVector *qiov); void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf); void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count); +ssize_t qemu_preadv(int fd, QEMUIOVector *qiov, off_t offset); +ssize_t qemu_pwritev(int fd, QEMUIOVector *qiov, off_t offset); + #endif /* dyngen-exec.h hack */ #endif diff --git a/qemu-io-syscalls.c b/qemu-io-syscalls.c new file mode 100644 index 0000000..79804d7 --- /dev/null +++ b/qemu-io-syscalls.c @@ -0,0 +1,152 @@ +/* + * preadv/pwritev implementation + * (c) 2008 Gerd Hoffmann + * + * 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; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + */ + +#include +#include + +/* --------------------------------------------------------------- */ +/* linux: preadv/pwritev syscall windup */ + +#ifndef HAVE_PREADV +# ifdef __linux__ +# include + +#if 0 +/* WARNING: Be sure you know what you are doing if you enable this. + * linux syscall code isn't upstream yet, syscall numbers are subject + * to change */ +# ifndef __NR_preadv +# ifdef __i386__ +# define __NR_preadv 333 +# define __NR_pwritev 334 +# endif +# ifdef __x86_64__ +# define __NR_preadv 295 +# define __NR_pwritev 296 +# endif +# endif +#endif + +# ifdef __NR_preadv +# define HAVE_PREADV 1 + +static ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) +{ + uint32_t pos_high = (offset >> 32) & 0xffffffff; + uint32_t pos_low = offset & 0xffffffff; + ssize_t ret; + + ret = syscall(__NR_preadv, fd, iov, iovcnt, pos_high, pos_low); + if (ret < 0) { + errno = -ret; + return -1; + } + return ret; +} + +static ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) +{ + uint32_t pos_high = (offset >> 32) & 0xffffffff; + uint32_t pos_low = offset & 0xffffffff; + ssize_t ret; + + ret = syscall(__NR_pwritev, fd, iov, iovcnt, pos_high, pos_low); + if (ret < 0) { + errno = -ret; + return -1; + } + return ret; +} + +# endif /* __NR_preadv */ +# endif /* __linux__ */ + +#endif /* HAVE_PREADV */ + +/* --------------------------------------------------------------- */ +/* preadv/pwritev emulation */ + +static ssize_t emulate_prwv(int fd, QEMUIOVector *qiov, + off_t offset, int is_write) +{ + uint8_t *buf; + ssize_t ret; + + buf = malloc(qiov->size); + if (NULL == buf) { + errno = ENOMEM; + return -1; + } + + if (is_write) { + qemu_iovec_to_buffer(qiov, buf); + ret = pwrite(fd, buf, qiov->size, offset); + } else { + ret = pread(fd, buf, qiov->size, offset); + if (ret > 0) + qemu_iovec_from_buffer(qiov, buf, ret); + } + + free(buf); + return ret; +} + +/* --------------------------------------------------------------- */ +/* qemu preadv/pwritev interface */ + +#ifdef HAVE_PREADV +static int preadv_present = 1; +#endif + +ssize_t qemu_preadv(int fd, QEMUIOVector *qiov, off_t offset) +{ +#ifdef HAVE_PREADV + ssize_t ret; + + if (preadv_present) { + ret = preadv(fd, qiov->iov, qiov->niov, offset); + if (ret < 0 && errno == ENOSYS) { + preadv_present = 0; + goto emulate; + } + return ret; + } +emulate: +#endif + + return emulate_prwv(fd, qiov, offset, 0); +} + +ssize_t qemu_pwritev(int fd, QEMUIOVector *qiov, off_t offset) +{ +#ifdef HAVE_PREADV + ssize_t ret; + + if (preadv_present) { + ret = pwritev(fd, qiov->iov, qiov->niov, offset); + if (ret < 0 && errno == ENOSYS) { + preadv_present = 0; + goto emulate; + } + return ret; + } +emulate: +#endif + + return emulate_prwv(fd, qiov, offset, 1); +} -- 1.6.1 --------------000604030103090505070809--