diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h index bf867b924c..21d60b5855 100644 --- a/hw/file-op-9p.h +++ b/hw/file-op-9p.h @@ -80,9 +80,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 ee630334b8..0d520201b4 100644 --- a/hw/virtio-9p-local.c +++ b/hw/virtio-9p-local.c @@ -168,21 +168,34 @@ 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); +#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 off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence) +static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov, + int iovcnt, off_t offset) { - return lseek(fd, offset, whence); -} - -static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov, - int iovcnt) -{ - 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) @@ -523,9 +536,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 867fcfa095..0e8772257b 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);