Patchwork [7/9] Convert walk into 2nd threading model

login
register
mail settings
Submitter Arun Bharadwaj
Date Oct. 14, 2010, 12:25 p.m.
Message ID <20101014122503.2238.96729.stgit@localhost6.localdomain6>
Download mbox | patch
Permalink /patch/67817/
State New
Headers show

Comments

Arun Bharadwaj - Oct. 14, 2010, 12:25 p.m.
From: Sripathi Kodi <sripathik@in.ibm.com>

Signed-off-by: Sripathi Kodi <sripathik@in.ibm.com>
---
 hw/virtio-9p.c |  161 ++++++++++++++++++++++----------------------------------
 hw/virtio-9p.h |    5 ++
 2 files changed, 68 insertions(+), 98 deletions(-)

Patch

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index cad21fd..e08f284 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1635,9 +1635,10 @@  out:
     qemu_free(vs);
 }
 
-static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
+static void v9fs_walk_do_complete(void *opaque)
 {
-    complete_pdu(s, vs->pdu, err);
+    V9fsWalkState *vs = (V9fsWalkState *)opaque;
+    complete_pdu(vs->s, vs->pdu, vs->err);
 
     if (vs->nwnames) {
         for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) {
@@ -1647,6 +1648,7 @@  static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
         qemu_free(vs->wnames);
         qemu_free(vs->qids);
     }
+    qemu_free(vs);
 }
 
 static void v9fs_walk_marshal(V9fsWalkState *vs)
@@ -1660,70 +1662,78 @@  static void v9fs_walk_marshal(V9fsWalkState *vs)
     }
 }
 
-static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
-                                                                int err)
+static void v9fs_walk_worker(ThreadletWork *work)
 {
-    if (err == -1) {
-        free_fid(s, vs->newfidp->fid);
-        v9fs_string_free(&vs->path);
-        err = -ENOENT;
+    V9fsWalkState *vs = container_of(work, V9fsWalkState, work);
+
+    vs->fidp = lookup_fid(vs->s, vs->fid);
+    if (vs->fidp == NULL) {
+        vs->err = -ENOENT;
         goto out;
     }
 
-    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
-
-    vs->name_idx++;
-    if (vs->name_idx < vs->nwnames) {
-        v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
-                                            vs->wnames[vs->name_idx].data);
-        v9fs_string_copy(&vs->newfidp->path, &vs->path);
+    qemu_rwmutex_rdlock(&global_rename_lock);
+    /* FIXME: is this really valid? */
+    if (vs->fid == vs->newfid) {
+        BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
 
-        err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
-        v9fs_walk_post_newfid_lstat(s, vs, err);
-        return;
-    }
+        while (vs->name_idx < vs->nwnames) {
+            v9fs_string_sprintf(&vs->path, "%s/%s",
+                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
+            v9fs_string_copy(&vs->fidp->path, &vs->path);
 
-    v9fs_string_free(&vs->path);
-    v9fs_walk_marshal(vs);
-    err = vs->offset;
-out:
-    v9fs_walk_complete(s, vs, err);
-}
+            vs->err = v9fs_do_lstat(vs->s, &vs->fidp->path, &vs->stbuf);
+            if (vs->err == -1) {
+                v9fs_string_free(&vs->path);
+                vs->err = -ENOENT;
+                goto out;
+            }
+            stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
+            vs->name_idx++;
+        }
+    } else {
+        vs->newfidp = alloc_fid(vs->s, vs->newfid);
+        if (vs->newfidp == NULL) {
+            vs->err = -EINVAL;
+            goto out;
+        }
 
-static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
-        int err)
-{
-    if (err == -1) {
-        v9fs_string_free(&vs->path);
-        err = -ENOENT;
-        goto out;
-    }
+        vs->newfidp->uid = vs->fidp->uid;
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
+        v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path);
 
-    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
-    vs->name_idx++;
-    if (vs->name_idx < vs->nwnames) {
+        while (vs->name_idx < vs->nwnames) {
+            v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
+                                vs->wnames[vs->name_idx].data);
+            v9fs_string_copy(&vs->newfidp->path, &vs->path);
 
-        v9fs_string_sprintf(&vs->path, "%s/%s",
-                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
-        v9fs_string_copy(&vs->fidp->path, &vs->path);
+            vs->err = v9fs_do_lstat(vs->s, &vs->newfidp->path, &vs->stbuf);
 
-        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-        v9fs_walk_post_oldfid_lstat(s, vs, err);
-        return;
+            if (vs->err == -1) {
+                free_fid(vs->s, vs->newfidp->fid);
+                v9fs_string_free(&vs->path);
+                vs->err = -ENOENT;
+                goto out;
+            }
+            stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
+            vs->name_idx++;
+        }
     }
-
     v9fs_string_free(&vs->path);
     v9fs_walk_marshal(vs);
-    err = vs->offset;
+    vs->err = vs->offset;
 out:
-    v9fs_walk_complete(s, vs, err);
+    qemu_rwmutex_unlock(&global_rename_lock);
+    v9fs_async_helper_done(v9fs_walk_do_complete, vs);
 }
 
+
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 {
-    int32_t fid, newfid;
     V9fsWalkState *vs;
-    int err = 0;
     int i;
 
     vs = qemu_malloc(sizeof(*vs));
@@ -1731,9 +1741,10 @@  static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
     vs->wnames = NULL;
     vs->qids = NULL;
     vs->offset = 7;
+    vs->s = s;
 
-    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid,
-                                            &newfid, &vs->nwnames);
+    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &vs->fid,
+                                            &vs->newfid, &vs->nwnames);
 
     if (vs->nwnames) {
         vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
@@ -1746,55 +1757,9 @@  static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
         }
     }
 
-    vs->fidp = lookup_fid(s, fid);
-    if (vs->fidp == NULL) {
-        err = -ENOENT;
-        goto out;
-    }
-
-    /* FIXME: is this really valid? */
-    if (fid == newfid) {
-
-        BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
-        v9fs_string_init(&vs->path);
-        vs->name_idx = 0;
-
-        if (vs->name_idx < vs->nwnames) {
-            v9fs_string_sprintf(&vs->path, "%s/%s",
-                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
-            v9fs_string_copy(&vs->fidp->path, &vs->path);
-
-            err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-            v9fs_walk_post_oldfid_lstat(s, vs, err);
-            return;
-        }
-    } else {
-        vs->newfidp = alloc_fid(s, newfid);
-        if (vs->newfidp == NULL) {
-            err = -EINVAL;
-            goto out;
-        }
-
-        vs->newfidp->uid = vs->fidp->uid;
-        v9fs_string_init(&vs->path);
-        vs->name_idx = 0;
-        v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path);
-
-        if (vs->name_idx < vs->nwnames) {
-            v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
-                                vs->wnames[vs->name_idx].data);
-            v9fs_string_copy(&vs->newfidp->path, &vs->path);
-
-            err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
-            v9fs_walk_post_newfid_lstat(s, vs, err);
-            return;
-        }
-    }
-
-    v9fs_walk_marshal(vs);
-    err = vs->offset;
-out:
-    v9fs_walk_complete(s, vs, err);
+    vs->work.func = v9fs_walk_worker;
+    submit_threadlet(&vs->work);
+    return;
 }
 
 static void v9fs_open_do_complete(void *opaque)
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 1581bbe..45631dd 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -296,6 +296,11 @@  typedef struct V9fsWalkState {
     V9fsString path;
     V9fsString *wnames;
     struct stat stbuf;
+    V9fsState *s;
+    int32_t fid;
+    int32_t newfid;
+    int32_t err;
+    ThreadletWork work;
 } V9fsWalkState;
 
 typedef struct V9fsOpenState {