diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 75d4be3..e95bf50 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1615,6 +1615,29 @@ out:
     qemu_free(vs);
 }
 
+/************************* v9fs_walk calls *****************************/
+static void v9fs_walk_do_lstat_old(ThreadletWork *work)
+{
+    V9fsWalkState *vs;
+
+    vs = container_of(work, V9fsWalkState, 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_walk_do_lstat_new(ThreadletWork *work)
+{
+    V9fsWalkState *vs;
+
+    vs = container_of(work, V9fsWalkState, work);
+    vs->err = v9fs_do_lstat(vs->s, &vs->newfidp->path, &vs->stbuf);
+    vs->v9fs_errno = errno;
+
+    v9fs_async_helper_done(vs->post_fn, vs);
+}
+
 static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
 {
     complete_pdu(s, vs->pdu, err);
@@ -1640,13 +1663,14 @@ static void v9fs_walk_marshal(V9fsWalkState *vs)
     }
 }
 
-static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
-                                                                int err)
+static void v9fs_walk_post_newfid_lstat(void *opaque)
 {
-    if (err == -1) {
-        free_fid(s, vs->newfidp->fid);
+    V9fsWalkState *vs = (V9fsWalkState *)opaque;
+
+    if (vs->err == -1) {
+        free_fid(vs->s, vs->newfidp->fid);
         v9fs_string_free(&vs->path);
-        err = -ENOENT;
+        vs->err = -ENOENT;
         goto out;
     }
 
@@ -1658,24 +1682,25 @@ static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
                                             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);
+        v9fs_do_async_posix(&vs->work, v9fs_walk_do_lstat_new, &vs->post_fn,
+                            v9fs_walk_post_newfid_lstat);
         return;
     }
 
     v9fs_string_free(&vs->path);
     v9fs_walk_marshal(vs);
-    err = vs->offset;
+    vs->err = vs->offset;
 out:
-    v9fs_walk_complete(s, vs, err);
+    v9fs_walk_complete(vs->s, vs, vs->err);
 }
 
-static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
-        int err)
+static void v9fs_walk_post_oldfid_lstat(void *opaque)
 {
-    if (err == -1) {
+    V9fsWalkState *vs = (V9fsWalkState *)opaque;
+
+    if (vs->err == -1) {
         v9fs_string_free(&vs->path);
-        err = -ENOENT;
+        vs->err = -ENOENT;
         goto out;
     }
 
@@ -1687,23 +1712,22 @@ static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
                 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);
+        v9fs_do_async_posix(&vs->work, v9fs_walk_do_lstat_old, &vs->post_fn,
+                            v9fs_walk_post_oldfid_lstat);
         return;
     }
 
     v9fs_string_free(&vs->path);
     v9fs_walk_marshal(vs);
-    err = vs->offset;
+    vs->err = vs->offset;
 out:
-    v9fs_walk_complete(s, vs, err);
+    v9fs_walk_complete(vs->s, vs, vs->err);
 }
 
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t fid, newfid;
     V9fsWalkState *vs;
-    int err = 0;
     int i;
 
     vs = qemu_malloc(sizeof(*vs));
@@ -1711,6 +1735,8 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
     vs->wnames = NULL;
     vs->qids = NULL;
     vs->offset = 7;
+    vs->err = 0;
+    vs->s = s;
 
     vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid,
                                             &newfid, &vs->nwnames);
@@ -1728,7 +1754,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 
     vs->fidp = lookup_fid(s, fid);
     if (vs->fidp == NULL) {
-        err = -ENOENT;
+        vs->err = -ENOENT;
         goto out;
     }
 
@@ -1744,14 +1770,14 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
                 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);
+            v9fs_do_async_posix(&vs->work, v9fs_walk_do_lstat_old,
+                                &vs->post_fn, v9fs_walk_post_oldfid_lstat);
             return;
         }
     } else {
         vs->newfidp = alloc_fid(s, newfid);
         if (vs->newfidp == NULL) {
-            err = -EINVAL;
+            vs->err = -EINVAL;
             goto out;
         }
 
@@ -1765,16 +1791,16 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
                                 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);
+            v9fs_do_async_posix(&vs->work, v9fs_walk_do_lstat_new,
+                                &vs->post_fn, v9fs_walk_post_newfid_lstat);
             return;
         }
     }
 
     v9fs_walk_marshal(vs);
-    err = vs->offset;
+    vs->err = vs->offset;
 out:
-    v9fs_walk_complete(s, vs, err);
+    v9fs_walk_complete(s, vs, vs->err);
 }
 
 /********************* v9fs_open calls *********************************/
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 294de83..f88b5fc 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;
+    int err;
+    int v9fs_errno;
+    ThreadletWork work;
+    void (*post_fn)(void *arg);
 } V9fsWalkState;
 
 typedef struct V9fsOpenState {
