* [Qemu-devel] [RfC / experimental patch] preadv/pwritev code for qemu
@ 2009-01-23 12:17 Gerd Hoffmann
0 siblings, 0 replies; only message in thread
From: Gerd Hoffmann @ 2009-01-23 12:17 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 179 bytes --]
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
[-- Attachment #2: 0003-preadv-writev-code-for-qemu.patch --]
[-- Type: text/plain, Size: 6415 bytes --]
>From 8b640cab61853efa622e17bb9145fe242fffc5a4 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 22 Jan 2009 16:22:41 +0100
Subject: [PATCH 3/3] preadv/writev code for qemu.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
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 <<EOF
+int main(void) { preadv; }
+EOF
+preadv=no
+if $cc $ARCH_CFLAGS -o $TMPE $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 <kraxel@redhat.com>
+ *
+ * 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 <qemu-common.h>
+#include <unistd.h>
+
+/* --------------------------------------------------------------- */
+/* linux: preadv/pwritev syscall windup */
+
+#ifndef HAVE_PREADV
+# ifdef __linux__
+# include <sys/syscall.h>
+
+#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
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2009-01-23 12:17 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-23 12:17 [Qemu-devel] [RfC / experimental patch] preadv/pwritev code for qemu Gerd Hoffmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).