* [Qemu-devel] [PATCH 3/3] native preadv/pwritev support
@ 2009-04-06 12:41 Christoph Hellwig
2009-04-06 13:17 ` Avi Kivity
0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2009-04-06 12:41 UTC (permalink / raw)
To: qemu-devel
unistd.h. This is the case currently on at least NetBSD and OpenBSD and
will hopefully soon be the case on Linux.
Thanks to Blue Swirl and Gerd Hoffmann for the configure autodetection
of preadv/pwritev.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: qemu/posix-aio-compat.c
===================================================================
--- qemu.orig/posix-aio-compat.c 2009-04-06 14:02:50.543569977 +0200
+++ qemu/posix-aio-compat.c 2009-04-06 14:02:52.540445071 +0200
@@ -33,6 +33,12 @@ static int cur_threads = 0;
static int idle_threads = 0;
static TAILQ_HEAD(, qemu_paiocb) request_list;
+#ifdef HAVE_PREADV
+static int preadv_present = 1;
+#else
+static int preadv_present = 0;
+#endif
+
static void die2(int err, const char *what)
{
fprintf(stderr, "%s failed: %s\n", what, strerror(err));
@@ -87,6 +93,36 @@ static size_t handle_aiocb_ioctl(struct
return ret;
}
+#ifdef HAVE_PREADV
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return preadv(fd, iov, nr_iov, offset);
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return pwritev(fd, iov, nr_iov, offset);
+}
+
+#else
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return -ENOSYS;
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return -ENOSYS;
+}
+
+#endif
+
/*
* Check if we need to copy the data in the aiocb into a new
* properly aligned buffer.
@@ -104,6 +140,29 @@ static int aiocb_needs_copy(struct qemu_
return 0;
}
+static size_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
+{
+ size_t offset = 0;
+ ssize_t len;
+
+ do {
+ if (aiocb->aio_type == QEMU_PAIO_WRITE)
+ len = qemu_pwritev(aiocb->aio_fildes,
+ aiocb->aio_iov,
+ aiocb->aio_niov,
+ aiocb->aio_offset + offset);
+ else
+ len = qemu_preadv(aiocb->aio_fildes,
+ aiocb->aio_iov,
+ aiocb->aio_niov,
+ aiocb->aio_offset + offset);
+ } while (len == -1 && errno == EINTR);
+
+ if (len == -1)
+ return -errno;
+ return len;
+}
+
static size_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
{
size_t offset = 0;
@@ -140,12 +199,34 @@ static size_t handle_aiocb_rw(struct qem
size_t nbytes;
char *buf;
- if (!aiocb_needs_copy(aiocb) && aiocb->aio_niov == 1) {
+ if (!aiocb_needs_copy(aiocb)) {
/*
* If there is just a single buffer, and it is properly aligned
* we can just use plain pread/pwrite without any problems.
*/
- return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
+ if (aiocb->aio_niov == 1)
+ return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
+
+ /*
+ * We have more than one iovec, and all are properly aligned.
+ *
+ * Try preadv/pwritev first and fall back to linearizing the
+ * buffer if it's not supported.
+ */
+ if (preadv_present) {
+ nbytes = handle_aiocb_rw_vector(aiocb);
+ if (nbytes == aiocb->aio_nbytes)
+ return nbytes;
+ if (nbytes < 0 && nbytes != -ENOSYS)
+ return nbytes;
+ preadv_present = 0;
+ }
+
+ /*
+ * XXX(hch): short read/write. no easy way to handle the reminder
+ * using these interfaces. For now retry using plain
+ * pread/pwrite?
+ */
}
/*
Index: qemu/configure
===================================================================
--- qemu.orig/configure 2009-04-06 14:00:48.658569843 +0200
+++ qemu/configure 2009-04-06 14:02:52.540445071 +0200
@@ -1108,6 +1108,19 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /de
fi
##########################################
+# preadv probe
+cat > $TMPC <<EOF
+#include <sys/types.h>
+#include <sys/uio.h>
+#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
@@ -1221,6 +1234,7 @@ echo "AIO support $aio"
echo "Install blobs $blobs"
echo "KVM support $kvm"
echo "fdt support $fdt"
+echo "preadv support $preadv"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1522,6 +1536,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
Index: qemu/block.c
===================================================================
--- qemu.orig/block.c 2009-04-06 14:02:50.538445233 +0200
+++ qemu/block.c 2009-04-06 14:02:52.554453627 +0200
@@ -1354,10 +1354,9 @@ static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
- qemu_vfree(acb->bounce);
-
if (!acb->is_write)
qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
+ qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, acb->ret);
qemu_aio_release(acb);
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] native preadv/pwritev support
2009-04-06 12:41 [Qemu-devel] [PATCH 3/3] native preadv/pwritev support Christoph Hellwig
@ 2009-04-06 13:17 ` Avi Kivity
2009-04-06 16:32 ` Christoph Hellwig
0 siblings, 1 reply; 3+ messages in thread
From: Avi Kivity @ 2009-04-06 13:17 UTC (permalink / raw)
To: qemu-devel
Christoph Hellwig wrote:
> unistd.h. This is the case currently on at least NetBSD and OpenBSD and
> will hopefully soon be the case on Linux.
>
> Thanks to Blue Swirl and Gerd Hoffmann for the configure autodetection
> of preadv/pwritev.
>
Looks like the log message got chopped.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH 3/3] native preadv/pwritev support
2009-04-06 13:17 ` Avi Kivity
@ 2009-04-06 16:32 ` Christoph Hellwig
0 siblings, 0 replies; 3+ messages in thread
From: Christoph Hellwig @ 2009-04-06 16:32 UTC (permalink / raw)
To: qemu-devel
This ties up the preadv/pwritev syscalls to qemu if they are declared in
unistd.h. This is the case currently on at least NetBSD and OpenBSD and
will hopefully soon be the case on Linux.
Thanks to Blue Swirl and Gerd Hoffmann for the configure autodetection
of preadv/pwritev.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: qemu/posix-aio-compat.c
===================================================================
--- qemu.orig/posix-aio-compat.c 2009-04-06 14:02:50.543569977 +0200
+++ qemu/posix-aio-compat.c 2009-04-06 14:02:52.540445071 +0200
@@ -33,6 +33,12 @@ static int cur_threads = 0;
static int idle_threads = 0;
static TAILQ_HEAD(, qemu_paiocb) request_list;
+#ifdef HAVE_PREADV
+static int preadv_present = 1;
+#else
+static int preadv_present = 0;
+#endif
+
static void die2(int err, const char *what)
{
fprintf(stderr, "%s failed: %s\n", what, strerror(err));
@@ -87,6 +93,36 @@ static size_t handle_aiocb_ioctl(struct
return ret;
}
+#ifdef HAVE_PREADV
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return preadv(fd, iov, nr_iov, offset);
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return pwritev(fd, iov, nr_iov, offset);
+}
+
+#else
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return -ENOSYS;
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return -ENOSYS;
+}
+
+#endif
+
/*
* Check if we need to copy the data in the aiocb into a new
* properly aligned buffer.
@@ -104,6 +140,29 @@ static int aiocb_needs_copy(struct qemu_
return 0;
}
+static size_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
+{
+ size_t offset = 0;
+ ssize_t len;
+
+ do {
+ if (aiocb->aio_type == QEMU_PAIO_WRITE)
+ len = qemu_pwritev(aiocb->aio_fildes,
+ aiocb->aio_iov,
+ aiocb->aio_niov,
+ aiocb->aio_offset + offset);
+ else
+ len = qemu_preadv(aiocb->aio_fildes,
+ aiocb->aio_iov,
+ aiocb->aio_niov,
+ aiocb->aio_offset + offset);
+ } while (len == -1 && errno == EINTR);
+
+ if (len == -1)
+ return -errno;
+ return len;
+}
+
static size_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
{
size_t offset = 0;
@@ -140,12 +199,34 @@ static size_t handle_aiocb_rw(struct qem
size_t nbytes;
char *buf;
- if (!aiocb_needs_copy(aiocb) && aiocb->aio_niov == 1) {
+ if (!aiocb_needs_copy(aiocb)) {
/*
* If there is just a single buffer, and it is properly aligned
* we can just use plain pread/pwrite without any problems.
*/
- return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
+ if (aiocb->aio_niov == 1)
+ return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
+
+ /*
+ * We have more than one iovec, and all are properly aligned.
+ *
+ * Try preadv/pwritev first and fall back to linearizing the
+ * buffer if it's not supported.
+ */
+ if (preadv_present) {
+ nbytes = handle_aiocb_rw_vector(aiocb);
+ if (nbytes == aiocb->aio_nbytes)
+ return nbytes;
+ if (nbytes < 0 && nbytes != -ENOSYS)
+ return nbytes;
+ preadv_present = 0;
+ }
+
+ /*
+ * XXX(hch): short read/write. no easy way to handle the reminder
+ * using these interfaces. For now retry using plain
+ * pread/pwrite?
+ */
}
/*
Index: qemu/configure
===================================================================
--- qemu.orig/configure 2009-04-06 14:00:48.658569843 +0200
+++ qemu/configure 2009-04-06 14:02:52.540445071 +0200
@@ -1108,6 +1108,19 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /de
fi
##########################################
+# preadv probe
+cat > $TMPC <<EOF
+#include <sys/types.h>
+#include <sys/uio.h>
+#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
@@ -1221,6 +1234,7 @@ echo "AIO support $aio"
echo "Install blobs $blobs"
echo "KVM support $kvm"
echo "fdt support $fdt"
+echo "preadv support $preadv"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1522,6 +1536,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
Index: qemu/block.c
===================================================================
--- qemu.orig/block.c 2009-04-06 14:02:50.538445233 +0200
+++ qemu/block.c 2009-04-06 14:02:52.554453627 +0200
@@ -1354,10 +1354,9 @@ static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
- qemu_vfree(acb->bounce);
-
if (!acb->is_write)
qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
+ qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, acb->ret);
qemu_aio_release(acb);
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-04-06 16:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-06 12:41 [Qemu-devel] [PATCH 3/3] native preadv/pwritev support Christoph Hellwig
2009-04-06 13:17 ` Avi Kivity
2009-04-06 16:32 ` Christoph Hellwig
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).