All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: ericvh@gmail.com, aliguori@us.ibm.com, aneesh.kumar@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH -V4 14/21] virtio-9p: Add P9_TREAD support
Date: Fri,  9 Apr 2010 17:13:17 +0530	[thread overview]
Message-ID: <1270813404-23004-15-git-send-email-aneesh.kumar@linux.vnet.ibm.com> (raw)
In-Reply-To: <1270813404-23004-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: Anthony Liguori <aliguori@us.ibm.com>

Implement P9_TREAD support.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/file-op-9p.h      |    6 ++
 hw/virtio-9p-local.c |   37 ++++++++
 hw/virtio-9p.c       |  234 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 275 insertions(+), 2 deletions(-)

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 715f2d0..c1f5e45 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -34,6 +34,12 @@ typedef struct FileOperations
     int (*closedir)(FsContext *, DIR *);
     DIR *(*opendir)(FsContext *, const char *);
     int (*open)(FsContext *, const char *, int);
+    void (*rewinddir)(FsContext *, DIR *);
+    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);
+    off_t (*lseek)(FsContext *, int, off_t, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 3788d4e..81d1971 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -96,6 +96,37 @@ static DIR *local_opendir(FsContext *ctx, const char *path)
     return opendir(rpath(ctx, path));
 }
 
+static void local_rewinddir(FsContext *ctx, DIR *dir)
+{
+    return rewinddir(dir);
+}
+
+static off_t local_telldir(FsContext *ctx, DIR *dir)
+{
+    return telldir(dir);
+}
+
+static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
+{
+    return readdir(dir);
+}
+
+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)
+{
+    return readv(fd, iov, iovcnt);
+}
+
+static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
+{
+    return lseek(fd, offset, whence);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -104,4 +135,10 @@ FileOperations local_ops = {
     .closedir = local_closedir,
     .open = local_open,
     .opendir = local_opendir,
+    .rewinddir = local_rewinddir,
+    .telldir = local_telldir,
+    .readdir = local_readdir,
+    .seekdir = local_seekdir,
+    .readv = local_readv,
+    .lseek = local_lseek,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index f4b7889..e702c5c 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -66,6 +66,37 @@ static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
     return s->ops->opendir(&s->ctx, path->data);
 }
 
+static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
+{
+    return s->ops->rewinddir(&s->ctx, dir);
+}
+
+static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
+{
+    return s->ops->telldir(&s->ctx, dir);
+}
+
+static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir)
+{
+    return s->ops->readdir(&s->ctx, dir);
+}
+
+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)
+{
+    return s->ops->readv(&s->ctx, fd, iov, iovcnt);
+}
+
+static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
+{
+    return s->ops->lseek(&s->ctx, fd, offset, whence);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1287,11 +1318,210 @@ static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsReadState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t count;
+    int32_t total;
+    int64_t off;
+    V9fsFidState *fidp;
+    struct iovec iov[128]; /* FIXME: bad, bad, bad */
+    struct iovec *sg;
+    off_t dir_pos;
+    struct dirent *dent;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsStat v9stat;
+    int32_t len;
+    int32_t cnt;
+    int32_t max_count;
+} V9fsReadState;
+
+static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t);
+
+static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (err) {
+        goto out;
+    }
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
+                                    ssize_t err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+    err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
+
+    vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S",
+                            &vs->v9stat);
+    if ((vs->len != (vs->v9stat.size + 2)) ||
+            ((vs->count + vs->len) > vs->max_count)) {
+        v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
+        v9fs_read_post_seekdir(s, vs, err);
+        return;
+    }
+    vs->count += vs->len;
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->dir_pos = vs->dent->d_off;
+    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+out:
+    v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
+    v9fs_read_post_seekdir(s, vs, err);
+    return;
+
+}
+
+static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (vs->dent) {
+        memset(&vs->v9stat, 0, sizeof(vs->v9stat));
+        v9fs_string_init(&vs->name);
+        v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
+                            vs->dent->d_name);
+        err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
+        v9fs_read_post_dir_lstat(s, vs, err);
+        return;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
+                                       ssize_t err)
+{
+    vs->dir_pos = v9fs_do_telldir(s, vs->fidp->dir);
+    v9fs_read_post_telldir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = v9fs_do_readv(s, vs->fidp->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;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+    vs->offset += vs->count;
+    err = vs->offset;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    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->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_read(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsReadState *vs;
+    ssize_t err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+    vs->total = 0;
+    vs->len = 0;
+    vs->count = 0;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dqd", &fid, &vs->off, &vs->count);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    if (vs->fidp->dir) {
+        vs->max_count = vs->count;
+        vs->count = 0;
+        if (vs->off == 0) {
+            v9fs_do_rewinddir(s, vs->fidp->dir);
+        }
+        v9fs_read_post_rewinddir(s, vs, err);
+        return;
+    } else if (vs->fidp->fd != -1) {
+        vs->sg = vs->iov;
+        pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
+        err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+        v9fs_read_post_lseek(s, vs, err);
+        return;
+    } else {
+        err = -EINVAL;
     }
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
-- 
1.7.0.4.360.g11766c

  parent reply	other threads:[~2010-04-09 11:44 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-09 11:43 [Qemu-devel] [PATCH -V4 00/21] virtio-9p: paravirtual file system passthrough Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 01/21] virtio-9p: Create a commandline option -fsdev Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 02/21] virtio-9p: Add a virtio 9p device to qemu Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 03/21] virtio-9p: pdu processing support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 04/21] virtio-9p: Add string manipulation support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 05/21] virtio-9p: Add minimal set of FileOperations Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 06/21] virtio-9p: Add fid and qid management support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 07/21] virtio-9p: Add stat and mode related helper functions Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 08/21] virtio-9p: Add sg " Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 09/21] virtio-9p: Add P9_TVERSION support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 10/21] virtio-9p: Add P9_TATTACH support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 11/21] virtio-9p: Add P9_TSTAT support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 12/21] virtio-9p: Add P9_TWALK support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 13/21] virtio-9p: Add P9_TOPEN support Aneesh Kumar K.V
2010-04-09 11:43 ` Aneesh Kumar K.V [this message]
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 15/21] virtio-9p: Add P9_TCLUNK support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 16/21] virtio-9p: Add P9_TWRITE support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 17/21] virtio-9p: Add P9_TCREATE support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 18/21] virtio-9p: Add P9_TWSTAT support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 19/21] virtio-9p: Add P9_TREMOVE support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 20/21] virtio-9p: Add P9_TFLUSH support Aneesh Kumar K.V
2010-04-09 11:43 ` [Qemu-devel] [PATCH -V4 21/21] virtio-9p: Create a syntactic shortcut for the file-system pass-thru Aneesh Kumar K.V

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1270813404-23004-15-git-send-email-aneesh.kumar@linux.vnet.ibm.com \
    --to=aneesh.kumar@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=ericvh@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.