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