From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LrGGj-0003DJ-Ay for qemu-devel@nongnu.org; Tue, 07 Apr 2009 14:43:33 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LrGGh-0003CV-Ag for qemu-devel@nongnu.org; Tue, 07 Apr 2009 14:43:31 -0400 Received: from [199.232.76.173] (port=37478 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LrGGg-0003CK-VI for qemu-devel@nongnu.org; Tue, 07 Apr 2009 14:43:31 -0400 Received: from savannah.gnu.org ([199.232.41.3]:48358 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LrGGf-00075a-SH for qemu-devel@nongnu.org; Tue, 07 Apr 2009 14:43:30 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1LrGGe-0000lb-Pi for qemu-devel@nongnu.org; Tue, 07 Apr 2009 18:43:28 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.69) (envelope-from ) id 1LrGGe-0000lX-IW for qemu-devel@nongnu.org; Tue, 07 Apr 2009 18:43:28 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Tue, 07 Apr 2009 18:43:28 +0000 Subject: [Qemu-devel] [7021] native preadv/pwritev support (Christoph Hellwig) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 7021 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=7021 Author: aliguori Date: 2009-04-07 18:43:28 +0000 (Tue, 07 Apr 2009) Log Message: ----------- native preadv/pwritev support (Christoph Hellwig) 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 Signed-off-by: Anthony Liguori Modified Paths: -------------- trunk/block.c trunk/configure trunk/posix-aio-compat.c Modified: trunk/block.c =================================================================== --- trunk/block.c 2009-04-07 18:43:24 UTC (rev 7020) +++ trunk/block.c 2009-04-07 18:43:28 UTC (rev 7021) @@ -1354,10 +1354,9 @@ { 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); Modified: trunk/configure =================================================================== --- trunk/configure 2009-04-07 18:43:24 UTC (rev 7020) +++ trunk/configure 2009-04-07 18:43:28 UTC (rev 7021) @@ -1108,6 +1108,19 @@ fi ########################################## +# preadv probe +cat > $TMPC < +#include +#include +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 "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 @@ 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 Modified: trunk/posix-aio-compat.c =================================================================== --- trunk/posix-aio-compat.c 2009-04-07 18:43:24 UTC (rev 7020) +++ trunk/posix-aio-compat.c 2009-04-07 18:43:28 UTC (rev 7021) @@ -33,6 +33,12 @@ 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 @@ 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 @@ 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 @@ 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? + */ } /*