diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 27e243e..02eb0ba 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -89,3 +89,138 @@ int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
     qemu_coroutine_yield();
     return vs.err;
 }
+
+typedef struct V9fsThChmodState {
+    int err;
+    mode_t mode;
+    V9fsState *s;
+    V9fsString *path;
+    V9fsRequest request;
+} V9fsThChmodState;
+
+static void v9fs_th_do_chmod(V9fsRequest *request)
+{
+    FsCred cred;
+    V9fsThChmodState *vsp = container_of(request, V9fsThChmodState,
+                                         request);
+    cred_init(&cred);
+    cred.fc_mode = vsp->mode;
+    vsp->err = vsp->s->ops->chmod(&vsp->s->ctx, vsp->path->data, &cred);
+    if (vsp->err < 0) {
+        vsp->err = -errno;
+    }
+}
+
+int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    V9fsThChmodState vs;
+    vs.s = s;
+    vs.path = path;
+    vs.mode = mode;
+    vs.request.func = v9fs_th_do_chmod;
+    vs.request.coroutine = qemu_coroutine_self();
+    v9fs_qemu_submit_request(&vs.request);
+    qemu_coroutine_yield();
+    return vs.err;
+}
+
+typedef struct V9fsThUtimeState {
+    int err;
+    V9fsState *s;
+    V9fsString *path;
+    struct timespec *times;
+    V9fsRequest request;
+} V9fsThUtimeState;
+
+static void v9fs_th_do_utimensat(V9fsRequest *request)
+{
+    V9fsThUtimeState *vsp = container_of(request, V9fsThUtimeState,
+                                         request);
+    vsp->err = vsp->s->ops->utimensat(&vsp->s->ctx,
+                                      vsp->path->data, vsp->times);
+    if (vsp->err < 0) {
+        vsp->err = -errno;
+    }
+}
+
+int v9fs_co_utimensat(V9fsState *s, V9fsString *path,
+                      struct timespec times[2])
+{
+    V9fsThUtimeState vs;
+    vs.s = s;
+    vs.path = path;
+    vs.times = times;
+    vs.request.func = v9fs_th_do_utimensat;
+    vs.request.coroutine = qemu_coroutine_self();
+    v9fs_qemu_submit_request(&vs.request);
+    qemu_coroutine_yield();
+    return vs.err;
+}
+
+typedef struct V9fsThChownState {
+    int err;
+    uid_t uid;
+    gid_t gid;
+    V9fsState *s;
+    V9fsString *path;
+    V9fsRequest request;
+} V9fsThChownState;
+
+static void v9fs_th_do_chown(V9fsRequest *request)
+{
+    FsCred cred;
+    V9fsThChownState *vsp = container_of(request, V9fsThChownState,
+                                         request);
+    cred_init(&cred);
+    cred.fc_uid = vsp->uid;
+    cred.fc_gid = vsp->gid;
+    vsp->err = vsp->s->ops->chown(&vsp->s->ctx, vsp->path->data, &cred);
+    if (vsp->err < 0) {
+        vsp->err = -errno;
+    }
+}
+
+int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
+{
+    V9fsThChownState vs;
+    vs.s = s;
+    vs.path = path;
+    vs.uid  = uid;
+    vs.gid  = gid;
+    vs.request.func = v9fs_th_do_chown;
+    vs.request.coroutine = qemu_coroutine_self();
+    v9fs_qemu_submit_request(&vs.request);
+    qemu_coroutine_yield();
+    return vs.err;
+}
+
+typedef struct V9fsThTruncateState {
+    int err;
+    off_t size;
+    V9fsState *s;
+    V9fsString *path;
+    V9fsRequest request;
+} V9fsThTruncateState;
+
+static void v9fs_th_do_truncate(V9fsRequest *request)
+{
+    V9fsThTruncateState *vsp = container_of(request, V9fsThTruncateState,
+                                            request);
+    vsp->err = vsp->s->ops->truncate(&vsp->s->ctx, vsp->path->data, vsp->size);
+    if (vsp->err < 0) {
+        vsp->err = -errno;
+    }
+}
+
+int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size)
+{
+    V9fsThTruncateState vs;
+    vs.s = s;
+    vs.path = path;
+    vs.size = size;
+    vs.request.func = v9fs_th_do_truncate;
+    vs.request.coroutine = qemu_coroutine_self();
+    v9fs_qemu_submit_request(&vs.request);
+    qemu_coroutine_yield();
+    return vs.err;
+}
diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
index aedeba9..4e2bc23 100644
--- a/hw/9pfs/virtio-9p-coth.h
+++ b/hw/9pfs/virtio-9p-coth.h
@@ -57,4 +57,8 @@ extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t);
 extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *);
 extern int v9fs_co_statfs(V9fsState *, V9fsString *, struct statfs *);
 extern int v9fs_co_lstat(V9fsState *, V9fsString *, struct stat *);
+extern int v9fs_co_chmod(V9fsState *, V9fsString *, mode_t);
+extern int v9fs_co_utimensat(V9fsState *, V9fsString *, struct timespec [2]);
+extern int v9fs_co_chown(V9fsState *, V9fsString *, uid_t, gid_t);
+extern int v9fs_co_truncate(V9fsState *, V9fsString *, off_t);
 #endif
