aboutsummaryrefslogtreecommitdiffstats
path: root/hw/virtio-9p.c
diff options
context:
space:
mode:
authorSanchit Garg <sancgarg@linux.vnet.ibm.com>2010-10-08 11:30:16 +0530
committerAnthony Liguori <aliguori@us.ibm.com>2010-10-20 12:10:59 -0500
commit56d15a53292c06a9c8c574e368003f57a06522ee (patch)
tree3b9dac4056f76e88c72f43b2984705b0a2f5eb86 /hw/virtio-9p.c
parent9f506893a454ce24263aba49594aa953e9a52853 (diff)
[virtio-9p] Use preadv/pwritev instead of readv/writev
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 <mohan@in.ibm.com> Signed-off-by: Sanchit Garg <sancgarg@linux.vnet.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Diffstat (limited to 'hw/virtio-9p.c')
-rw-r--r--hw/virtio-9p.c116
1 files changed, 39 insertions, 77 deletions
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 867fcfa09..0e8772257 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -135,21 +135,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)
@@ -1975,7 +1970,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 */
@@ -1989,12 +1984,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);
@@ -2006,32 +2005,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;
@@ -2089,8 +2062,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);
@@ -2224,7 +2205,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) {
@@ -2239,49 +2220,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;
@@ -2362,11 +2319,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);