qemu-devel
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]