* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.