[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 6/6] experimental native preadv/pwritev support
From: |
Gerd Hoffmann |
Subject: |
Re: [Qemu-devel] [PATCH 6/6] experimental native preadv/pwritev support for Linux |
Date: |
Mon, 16 Mar 2009 12:38:24 +0100 |
User-agent: |
Thunderbird 2.0.0.19 (X11/20090105) |
Christoph Hellwig wrote:
>
> This ties up Gerd Hoffmann's unmegred preadv/pwritev syscalls to qemu. Use
> with
> care as the syscall numbers aren't finalized yet.
>
> If someone of the BSD folks is interested it should be trivial to tie this up
> for the preadv/pwritev syscalls that have been around there for a while.
>
> Probably wants some optimization to not try preadv/pwritev again once we got
> the first ENOSYS.
See $patch I've hacked up a while ago. I think it already ran over the
list a while ago, /me was waiting for the preadv kernel patches hitting
mainline before trying to re-submit with the final syscall numbers and
the warning removed.
It provides qemu_p{read,write}v() functions. Adds autoconf check for
*BSD, does linux syscall windup, runtime check and emulation for old
kernels.
HTH,
Gerd
>From 5ab001859f3abeb792ef22d073d2bc38f6bb8604 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <address@hidden>
Date: Thu, 22 Jan 2009 16:22:41 +0100
Subject: [PATCH] preadv/writev code for qemu.
---
Makefile | 1 +
configure | 14 +++++
qemu-common.h | 3 +
qemu-io-syscalls.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 158 insertions(+), 0 deletions(-)
create mode 100644 qemu-io-syscalls.c
diff --git a/Makefile b/Makefile
index 4f7a55a..7921d54 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 c3fbbbe..a873cf4 100755
--- a/configure
+++ b/configure
@@ -1037,6 +1037,17 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2>
/dev/null ; then
fi
##########################################
+# preadv probe
+cat > $TMPC <<EOF
+#include <unistd.h>
+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
@@ -1432,6 +1443,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..f96e35a
--- /dev/null
+++ b/qemu-io-syscalls.c
@@ -0,0 +1,140 @@
+/*
+ * 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;
+
+ return syscall(__NR_preadv, fd, iov, iovcnt, pos_high, pos_low);
+}
+
+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;
+
+ return syscall(__NR_pwritev, fd, iov, iovcnt, pos_high, pos_low);
+}
+
+# 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.3
- Re: [Qemu-devel] [PATCH 2/6] change vectored block I/O API to plain iovecs, (continued)
[Qemu-devel] [PATCH 3/6] virtio-blk: use generic vectored I/O APIs, Christoph Hellwig, 2009/03/14
[Qemu-devel] [PATCH 4/6] remove bdrv_aio_read/bdrv_aio_write, Christoph Hellwig, 2009/03/14
[Qemu-devel] [PATCH 5/6] push down vector linearization to posix-aio-compat.c, Christoph Hellwig, 2009/03/14
[Qemu-devel] [PATCH 6/6] experimental native preadv/pwritev support for Linux, Christoph Hellwig, 2009/03/14
Re: [Qemu-devel] [PATCH 6/6] experimental native preadv/pwritev support for Linux,
Gerd Hoffmann <=