Patchwork [2/6] This patch converts v9fs_wstat() to make use of the threadlets infrastructure.

login
register
mail settings
Submitter Arun Bharadwaj
Date Oct. 13, 2010, 5:21 p.m.
Message ID <20101013172145.24213.79210.stgit@localhost6.localdomain6>
Download mbox | patch
Permalink /patch/67714/
State New
Headers show

Comments

Arun Bharadwaj - Oct. 13, 2010, 5:21 p.m.
From: Gautham R Shenoy <ego@in.ibm.com>

This patch offloads all the blocking calls invoked for v9fs_wstat onto
the helper threads belonging to the threadlets infrastructure.The handling
of the v9fs_post_*wstat* calls is done from the io-thread context.

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---
 hw/virtio-9p.c |  291 +++++++++++++++++++++++++++++++++++++++++++++-----------
 hw/virtio-9p.h |    7 +
 2 files changed, 243 insertions(+), 55 deletions(-)

Patch

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 5f6ce56..cf7e012 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -2853,36 +2853,126 @@  out:
     qemu_free(vs);
 }
 
-static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err)
+/*********************** v9fs_wstat operations ************************/
+
+static void v9fs_wstat_do_fsync(ThreadletWork *work)
+ {
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_fsync(vs->s, vs->fidp->fs.fd);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
+static void v9fs_wstat_do_lstat(ThreadletWork *work)
 {
-    if (err < 0) {
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_lstat(vs->s, &vs->fidp->path, &vs->stbuf);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
+static void v9fs_wstat_do_utimensat(ThreadletWork *work)
+{
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_utimensat(vs->s, &vs->fidp->path, vs->times);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+
+}
+
+static void v9fs_wstat_do_chmod(ThreadletWork *work)
+{
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_chmod(vs->s, &vs->fidp->path,
+                      v9mode_to_mode(vs->v9stat.mode,
+                      &vs->v9stat.extension));
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
+static void v9fs_wstat_do_chown(ThreadletWork *work)
+{
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_chown(vs->s, &vs->fidp->path, vs->v9stat.n_uid,
+                            vs->v9stat.n_gid);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
+static void v9fs_wstat_do_rename(ThreadletWork *work)
+{
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_rename(vs->s, &vs->fidp->path, &vs->nname);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
+static void v9fs_wstat_do_truncate(ThreadletWork *work)
+{
+    V9fsWstatState *vs;
+
+    vs = container_of(work, V9fsWstatState, work);
+    vs->err = v9fs_do_truncate(vs->s, &vs->fidp->path,
+                               vs->v9stat.length);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
+static void v9fs_wstat_post_truncate(void *opaque)
+{
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
+
+    if (vs->err < 0) {
+        vs->err = -vs->v9fs_errno;
         goto out;
     }
 
-    err = vs->offset;
+    vs->err = vs->offset;
 
 out:
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(vs->s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
-static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
+static void v9fs_wstat_post_rename(void *opaque)
 {
-    if (err < 0) {
+     V9fsWstatState *vs = (V9fsWstatState *)opaque;
+
+    if (vs->err < 0) {
+        vs->err = -vs->v9fs_errno;
         goto out;
     }
     if (vs->v9stat.length != -1) {
-        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
-            err = -errno;
-        }
+        v9fs_do_async_posix(&vs->work, v9fs_wstat_do_truncate,
+                            &vs->post_fn, v9fs_wstat_post_truncate);
+        return;
     }
-    v9fs_wstat_post_truncate(s, vs, err);
+    v9fs_wstat_post_truncate(vs);
     return;
 
 out:
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(vs->s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
@@ -2964,6 +3054,7 @@  static void v9fs_rename_post_rename(V9fsState *s, V9fsRenameState *vs, int err)
     qemu_free(vs);
 }
 
+#if 0
 static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
 {
     if (err < 0) {
@@ -2992,6 +3083,91 @@  out:
     complete_pdu(s, vs->pdu, err);
     qemu_free(vs);
 }
+#endif
+
+static void v9fs_wstat_post_rename_new(void *opaque)
+{
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
+    V9fsFidState *fidp;
+
+    if (vs->err < 0) {
+        vs->err = -vs->v9fs_errno;
+        goto out;
+    }
+
+    /*
+     * Fixup fid's pointing to the old name to
+     * start pointing to the new name
+     */
+    for (fidp = vs->s->fid_list; fidp; fidp = fidp->next) {
+        if (vs->fidp == fidp) {
+            /*
+             * we replace name of this fid towards the end
+             * so that our below strcmp will work
+             */
+            continue;
+        }
+        if (!strncmp(vs->fidp->path.data, fidp->path.data,
+            strlen(vs->fidp->path.data))) {
+            /* replace the name */
+            v9fs_fix_path(&fidp->path, &vs->nname,
+            strlen(vs->fidp->path.data));
+        }
+    }
+
+    v9fs_string_copy(&vs->fidp->path, &vs->nname);
+
+out:
+    v9fs_wstat_post_rename(vs);
+    return;
+}
+
+static void v9fs_wstat_post_chown(void *opaque)
+{
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
+
+    if (vs->err < 0) {
+        vs->err = -vs->v9fs_errno;
+        goto out;
+    }
+
+    if (vs->v9stat.name.size != 0) {
+        char *old_name, *new_name;
+        char *end;
+
+        old_name = vs->fidp->path.data;
+        end = strrchr(old_name, '/');
+        if (end) {
+            end++;
+        } else {
+            end = old_name;
+        }
+
+        new_name = qemu_malloc(end - old_name + vs->v9stat.name.size + 1);
+
+        memset(new_name, 0, end - old_name + vs->v9stat.name.size + 1);
+        memcpy(new_name, old_name, end - old_name);
+        memcpy(new_name + (end - old_name), vs->v9stat.name.data,
+                vs->v9stat.name.size);
+        vs->nname.data = new_name;
+        vs->nname.size = strlen(new_name);
+
+        if (strcmp(new_name, vs->fidp->path.data) != 0) {
+            v9fs_do_async_posix(&vs->work, v9fs_wstat_do_rename,
+                                &vs->post_fn, v9fs_wstat_post_rename_new);
+            return;
+        }
+    }
+
+    v9fs_wstat_post_rename(vs);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(vs->s, vs->pdu, vs->err);
+    qemu_free(vs);
+}
+
 
 static void v9fs_rename(V9fsState *s, V9fsPDU *pdu)
 {
@@ -3021,78 +3197,85 @@  out:
     qemu_free(vs);
 }
 
-static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
+static void v9fs_wstat_post_utime(void *opaque)
 {
-    if (err < 0) {
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
+
+    if (vs->err < 0) {
+        vs->err = -vs->v9fs_errno;
         goto out;
     }
 
     if (vs->v9stat.n_gid != -1 || vs->v9stat.n_uid != -1) {
-        if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
-                    vs->v9stat.n_gid)) {
-            err = -errno;
-        }
+        v9fs_do_async_posix(&vs->work, v9fs_wstat_do_chown, &vs->post_fn,
+                            v9fs_wstat_post_chown);
+        return;
     }
-    v9fs_wstat_post_chown(s, vs, err);
+    v9fs_wstat_post_chown(vs);
     return;
 
 out:
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(vs->s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
-static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
+static void v9fs_wstat_post_chmod(void *opaque)
 {
-    if (err < 0) {
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
+
+    if (vs->err < 0) {
+        vs->err = -vs->v9fs_errno;
         goto out;
     }
 
     if (vs->v9stat.mtime != -1 || vs->v9stat.atime != -1) {
-        struct timespec times[2];
         if (vs->v9stat.atime != -1) {
-            times[0].tv_sec = vs->v9stat.atime;
-            times[0].tv_nsec = 0;
+            vs->times[0].tv_sec = vs->v9stat.atime;
+            vs->times[0].tv_nsec = 0;
         } else {
-            times[0].tv_nsec = UTIME_OMIT;
+            vs->times[0].tv_nsec = UTIME_OMIT;
         }
         if (vs->v9stat.mtime != -1) {
-            times[1].tv_sec = vs->v9stat.mtime;
-            times[1].tv_nsec = 0;
+            vs->times[1].tv_sec = vs->v9stat.mtime;
+            vs->times[1].tv_nsec = 0;
         } else {
-            times[1].tv_nsec = UTIME_OMIT;
+            vs->times[1].tv_nsec = UTIME_OMIT;
         }
 
-        if (v9fs_do_utimensat(s, &vs->fidp->path, times)) {
-            err = -errno;
-        }
+        v9fs_do_async_posix(&vs->work, v9fs_wstat_do_utimensat,
+                            &vs->post_fn, v9fs_wstat_post_utime);
+        return;
     }
 
-    v9fs_wstat_post_utime(s, vs, err);
+    v9fs_wstat_post_utime(vs);
     return;
 
 out:
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(vs->s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
-static void v9fs_wstat_post_fsync(V9fsState *s, V9fsWstatState *vs, int err)
+static void v9fs_wstat_post_fsync(void *opaque)
 {
-    if (err == -1) {
-        err = -errno;
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
+
+    if (vs->err == -1) {
+        vs->err = -vs->v9fs_errno;
     }
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(vs->s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
-static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
+static void v9fs_wstat_post_lstat(void *opaque)
 {
     uint32_t v9_mode;
+    V9fsWstatState *vs = (V9fsWstatState *)opaque;
 
-    if (err == -1) {
-        err = -errno;
+    if (vs->err == -1) {
+        vs->err = -vs->v9fs_errno;
         goto out;
     }
 
@@ -3101,20 +3284,17 @@  static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
     if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
         (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
             /* Attempting to change the type */
-            err = -EIO;
+            vs->err = -EIO;
             goto out;
     }
 
-    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
-                    &vs->v9stat.extension))) {
-            err = -errno;
-     }
-    v9fs_wstat_post_chmod(s, vs, err);
+    v9fs_do_async_posix(&vs->work, v9fs_wstat_do_chmod, &vs->post_fn,
+                        v9fs_wstat_post_chmod);
     return;
 
 out:
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(vs->s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
@@ -3122,39 +3302,40 @@  static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t fid;
     V9fsWstatState *vs;
-    int err = 0;
 
     vs = qemu_malloc(sizeof(*vs));
     vs->pdu = pdu;
     vs->offset = 7;
+    vs->s = s;
+    vs->err = 0;
 
     pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat);
 
     vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
-        err = -EINVAL;
+        vs->err = -EINVAL;
         goto out;
     }
 
     /* do we need to sync the file? */
     if (donttouch_stat(&vs->v9stat)) {
-        err = v9fs_do_fsync(s, vs->fidp->fs.fd);
-        v9fs_wstat_post_fsync(s, vs, err);
+        v9fs_do_async_posix(&vs->work, v9fs_wstat_do_fsync, &vs->post_fn,
+                            v9fs_wstat_post_fsync);
         return;
     }
 
     if (vs->v9stat.mode != -1) {
-        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
-        v9fs_wstat_post_lstat(s, vs, err);
+        v9fs_do_async_posix(&vs->work, v9fs_wstat_do_lstat, &vs->post_fn,
+                            v9fs_wstat_post_lstat);
         return;
     }
 
-    v9fs_wstat_post_chmod(s, vs, err);
+    v9fs_wstat_post_chmod(vs);
     return;
 
 out:
     v9fs_stat_free(&vs->v9stat);
-    complete_pdu(s, vs->pdu, err);
+    complete_pdu(s, vs->pdu, vs->err);
     qemu_free(vs);
 }
 
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 769d3fc..74d7b68 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -354,6 +354,13 @@  typedef struct V9fsWstatState
     V9fsStat v9stat;
     V9fsFidState *fidp;
     struct stat stbuf;
+    V9fsString nname;
+    V9fsState *s;
+    int err;
+    int v9fs_errno;
+    struct timespec times[2];
+    ThreadletWork work;
+    void (*post_fn)(void *arg);
 } V9fsWstatState;
 
 typedef struct V9fsSymlinkState