From patchwork Wed Oct 6 09:55:15 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sanchit Garg X-Patchwork-Id: 66903 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 82231B6ED0 for ; Wed, 6 Oct 2010 21:07:22 +1100 (EST) Received: from localhost ([127.0.0.1]:41618 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1P3Qu6-0002al-4m for incoming@patchwork.ozlabs.org; Wed, 06 Oct 2010 06:07:18 -0400 Received: from [140.186.70.92] (port=57200 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1P3Qs0-0001wV-N9 for qemu-devel@nongnu.org; Wed, 06 Oct 2010 06:05:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P3QiZ-00010d-VR for qemu-devel@nongnu.org; Wed, 06 Oct 2010 05:55:25 -0400 Received: from e23smtp09.au.ibm.com ([202.81.31.142]:57189) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P3QiZ-000107-3o for qemu-devel@nongnu.org; Wed, 06 Oct 2010 05:55:23 -0400 Received: from d23relay04.au.ibm.com (d23relay04.au.ibm.com [202.81.31.246]) by e23smtp09.au.ibm.com (8.14.4/8.13.1) with ESMTP id o969tJR8027121 for ; Wed, 6 Oct 2010 20:55:19 +1100 Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o969tJpJ2474002 for ; Wed, 6 Oct 2010 20:55:19 +1100 Received: from d23av03.au.ibm.com (loopback [127.0.0.1]) by d23av03.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o969tISe006016 for ; Wed, 6 Oct 2010 20:55:19 +1100 Received: from sancgarg.in.ibm.com ([9.124.218.142]) by d23av03.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id o969tHYO005990; Wed, 6 Oct 2010 20:55:17 +1100 To: qemu-devel@nongnu.org From: Sanchit Garg Date: Wed, 06 Oct 2010 15:25:15 +0530 Message-ID: <20101006095515.27581.32369.stgit@sancgarg.in.ibm.com> User-Agent: StGit/0.15 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: "M. Mohan Kumar" Subject: [Qemu-devel] [PATCH] Use preadv/pwritev instead of readv/writev X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org readv & writev, read & write respectively from the current offset of the file & hence their use has to be preceeded by a call to lseek. preadv/writev can be used instead, as they take the offset as an argument. This saves one system call( lseek ). In case preadv is not supported, it is implemented by an lseek followed by a readv. Depending upon the configuration of QEMU, the appropriate read & write methods are selected. This patch also fixes the zero byte read/write bug & obviates the need to apply a fix for that bug separately. Signed-off-by: M. Mohan Kumar Signed-off-by: Sanchit Garg --- hw/file-op-9p.h | 5 +- hw/virtio-9p-local.c | 48 +++++++++++++++------ hw/virtio-9p.c | 116 +++++++++++++++++--------------------------------- 3 files changed, 75 insertions(+), 94 deletions(-) diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h index d91b7e7..31a834d 100644 --- a/hw/file-op-9p.h +++ b/hw/file-op-9p.h @@ -77,9 +77,8 @@ typedef struct FileOperations off_t (*telldir)(FsContext *, DIR *); struct dirent *(*readdir)(FsContext *, DIR *); void (*seekdir)(FsContext *, DIR *, off_t); - ssize_t (*readv)(FsContext *, int, const struct iovec *, int); - ssize_t (*writev)(FsContext *, int, const struct iovec *, int); - off_t (*lseek)(FsContext *, int, off_t, int); + ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t); + ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t); int (*mkdir)(FsContext *, const char *, FsCred *); int (*fstat)(FsContext *, int, struct stat *); int (*rename)(FsContext *, const char *, const char *); diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c index 57f9243..eb276ef 100644 --- a/hw/virtio-9p-local.c +++ b/hw/virtio-9p-local.c @@ -175,21 +175,42 @@ static void local_seekdir(FsContext *ctx, DIR *dir, off_t off) return seekdir(dir, off); } -static ssize_t local_readv(FsContext *ctx, int fd, const struct iovec *iov, - int iovcnt) +static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov, + int iovcnt, off_t offset) { - return readv(fd, iov, iovcnt); -} - -static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence) -{ - return lseek(fd, offset, whence); +#ifdef CONFIG_PREADV + { + return preadv(fd, iov, iovcnt, offset); + } +#else + { + int err = lseek(fd, offset, SEEK_SET); + if (err == -1) { + return err; + } else { + return readv(fd, iov, iovcnt); + } + } +#endif } -static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov, - int iovcnt) +static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov, + int iovcnt, off_t offset) { - return writev(fd, iov, iovcnt); +#ifdef CONFIG_PREADV + { + return pwritev(fd, iov, iovcnt, offset); + } +#else + { + int err = lseek(fd, offset, SEEK_SET); + if (err == -1) { + return err; + } else { + return writev(fd, iov, iovcnt); + } + } +#endif } static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp) @@ -608,9 +629,8 @@ FileOperations local_ops = { .telldir = local_telldir, .readdir = local_readdir, .seekdir = local_seekdir, - .readv = local_readv, - .lseek = local_lseek, - .writev = local_writev, + .preadv = local_preadv, + .pwritev = local_pwritev, .chmod = local_chmod, .mknod = local_mknod, .mkdir = local_mkdir, diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index 33718ea..9ef0667 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -134,21 +134,16 @@ static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off) return s->ops->seekdir(&s->ctx, dir, off); } -static int v9fs_do_readv(V9fsState *s, int fd, const struct iovec *iov, - int iovcnt) +static int v9fs_do_preadv(V9fsState *s, int fd, const struct iovec *iov, + int iovcnt, int64_t offset) { - return s->ops->readv(&s->ctx, fd, iov, iovcnt); + return s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); } -static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence) +static int v9fs_do_pwritev(V9fsState *s, int fd, const struct iovec *iov, + int iovcnt, int64_t offset) { - return s->ops->lseek(&s->ctx, fd, offset, whence); -} - -static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov, - int iovcnt) -{ - return s->ops->writev(&s->ctx, fd, iov, iovcnt); + return s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); } static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode) @@ -1941,7 +1936,7 @@ static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs, return; } -static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err) +static void v9fs_read_post_preadv(V9fsState *s, V9fsReadState *vs, ssize_t err) { if (err < 0) { /* IO error return the error */ @@ -1955,12 +1950,16 @@ static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err) if (0) { print_sg(vs->sg, vs->cnt); } - vs->len = v9fs_do_readv(s, vs->fidp->fs.fd, vs->sg, vs->cnt); + vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt, + vs->off); + if (vs->len > 0) { + vs->off += vs->len; + } } while (vs->len == -1 && errno == EINTR); if (vs->len == -1) { err = -errno; } - v9fs_read_post_readv(s, vs, err); + v9fs_read_post_preadv(s, vs, err); return; } vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total); @@ -1972,32 +1971,6 @@ out: qemu_free(vs); } -static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err) -{ - if (err == -1) { - err = -errno; - goto out; - } - vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); - - if (vs->total < vs->count) { - do { - if (0) { - print_sg(vs->sg, vs->cnt); - } - vs->len = v9fs_do_readv(s, vs->fidp->fs.fd, vs->sg, vs->cnt); - } while (vs->len == -1 && errno == EINTR); - if (vs->len == -1) { - err = -errno; - } - v9fs_read_post_readv(s, vs, err); - return; - } -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - static void v9fs_xattr_read(V9fsState *s, V9fsReadState *vs) { ssize_t err = 0; @@ -2055,8 +2028,16 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu) } else if (vs->fidp->fid_type == P9_FID_FILE) { vs->sg = vs->iov; pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt); - err = v9fs_do_lseek(s, vs->fidp->fs.fd, vs->off, SEEK_SET); - v9fs_read_post_lseek(s, vs, err); + vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); + if (vs->total <= vs->count) { + vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt, + vs->off); + if (vs->len > 0) { + vs->off += vs->len; + } + err = vs->len; + v9fs_read_post_preadv(s, vs, err); + } return; } else if (vs->fidp->fid_type == P9_FID_XATTR) { v9fs_xattr_read(s, vs); @@ -2190,7 +2171,7 @@ out: return; } -static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs, +static void v9fs_write_post_pwritev(V9fsState *s, V9fsWriteState *vs, ssize_t err) { if (err < 0) { @@ -2205,49 +2186,25 @@ static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs, if (0) { print_sg(vs->sg, vs->cnt); } - vs->len = v9fs_do_writev(s, vs->fidp->fs.fd, vs->sg, vs->cnt); + vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, + vs->off); + if (vs->len > 0) { + vs->off += vs->len; + } } while (vs->len == -1 && errno == EINTR); if (vs->len == -1) { err = -errno; } - v9fs_write_post_writev(s, vs, err); + v9fs_write_post_pwritev(s, vs, err); return; } vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total); - err = vs->offset; out: complete_pdu(s, vs->pdu, err); qemu_free(vs); } -static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err) -{ - if (err == -1) { - err = -errno; - goto out; - } - vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); - - if (vs->total < vs->count) { - do { - if (0) { - print_sg(vs->sg, vs->cnt); - } - vs->len = v9fs_do_writev(s, vs->fidp->fs.fd, vs->sg, vs->cnt); - } while (vs->len == -1 && errno == EINTR); - if (vs->len == -1) { - err = -errno; - } - v9fs_write_post_writev(s, vs, err); - return; - } - -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) { int i, to_copy; @@ -2328,11 +2285,16 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu) err = -EINVAL; goto out; } - err = v9fs_do_lseek(s, vs->fidp->fs.fd, vs->off, SEEK_SET); - - v9fs_write_post_lseek(s, vs, err); + vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); + if (vs->total <= vs->count) { + vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, vs->off); + if (vs->len > 0) { + vs->off += vs->len; + } + err = vs->len; + v9fs_write_post_pwritev(s, vs, err); + } return; - out: complete_pdu(s, vs->pdu, err); qemu_free(vs);