[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RfC / experimental patch] preadv/pwritev code for qemu
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [RfC / experimental patch] preadv/pwritev code for qemu |
Date: |
Fri, 23 Jan 2009 13:17:16 +0100 |
User-agent: |
Thunderbird 2.0.0.19 (X11/20090105) |
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
>From 8b640cab61853efa622e17bb9145fe242fffc5a4 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <address@hidden>
Date: Thu, 22 Jan 2009 16:22:41 +0100
Subject: [PATCH 3/3] preadv/writev code for qemu.
Signed-off-by: Gerd Hoffmann <address@hidden>
---
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 <address@hidden>
+ *
+ * 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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [RfC / experimental patch] preadv/pwritev code for qemu,
Gerd Hoffmann <=