@@ -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);
}
@@ -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