1 2 /* 3 * Virtio 9p backend 4 * 5 * Copyright IBM, Corp. 2011 6 * 7 * Authors: 8 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 9 * 10 * This work is licensed under the terms of the GNU GPL, version 2. See 11 * the COPYING file in the top-level directory. 12 * 13 */ 14 15 #include "fsdev/qemu-fsdev.h" 16 #include "qemu-thread.h" 17 #include "qemu-coroutine.h" 18 #include "virtio-9p-coth.h" 19 20 int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf) 21 { 22 int err; 23 ssize_t len; 24 25 buf->data = g_malloc(PATH_MAX); 26 qemu_co_rwlock_rdlock(&s->rename_lock); 27 28 v9fs_co_run_in_worker( 29 { 30 len = s->ops->readlink(&s->ctx, path->data, 31 buf->data, PATH_MAX - 1); 32 if (len > -1) { 33 buf->size = len; 34 buf->data[len] = 0; 35 err = 0; 36 } else { 37 err = -errno; 38 } 39 }); 40 qemu_co_rwlock_unlock(&s->rename_lock); 41 if (err) { 42 g_free(buf->data); 43 buf->data = NULL; 44 buf->size = 0; 45 } 46 return err; 47 } 48 49 int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) 50 { 51 int err; 52 53 qemu_co_rwlock_rdlock(&s->rename_lock); 54 v9fs_co_run_in_worker( 55 { 56 err = s->ops->statfs(&s->ctx, path->data, stbuf); 57 if (err < 0) { 58 err = -errno; 59 } 60 }); 61 qemu_co_rwlock_unlock(&s->rename_lock); 62 return err; 63 } 64 65 int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode) 66 { 67 int err; 68 FsCred cred; 69 70 cred_init(&cred); 71 cred.fc_mode = mode; 72 qemu_co_rwlock_rdlock(&s->rename_lock); 73 v9fs_co_run_in_worker( 74 { 75 err = s->ops->chmod(&s->ctx, path->data, &cred); 76 if (err < 0) { 77 err = -errno; 78 } 79 }); 80 qemu_co_rwlock_unlock(&s->rename_lock); 81 return err; 82 } 83 84 int v9fs_co_utimensat(V9fsState *s, V9fsString *path, 85 struct timespec times[2]) 86 { 87 int err; 88 89 qemu_co_rwlock_rdlock(&s->rename_lock); 90 v9fs_co_run_in_worker( 91 { 92 err = s->ops->utimensat(&s->ctx, path->data, times); 93 if (err < 0) { 94 err = -errno; 95 } 96 }); 97 qemu_co_rwlock_unlock(&s->rename_lock); 98 return err; 99 } 100 101 int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid) 102 { 103 int err; 104 FsCred cred; 105 106 cred_init(&cred); 107 cred.fc_uid = uid; 108 cred.fc_gid = gid; 109 qemu_co_rwlock_rdlock(&s->rename_lock); 110 v9fs_co_run_in_worker( 111 { 112 err = s->ops->chown(&s->ctx, path->data, &cred); 113 if (err < 0) { 114 err = -errno; 115 } 116 }); 117 qemu_co_rwlock_unlock(&s->rename_lock); 118 return err; 119 } 120 121 int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size) 122 { 123 int err; 124 125 qemu_co_rwlock_rdlock(&s->rename_lock); 126 v9fs_co_run_in_worker( 127 { 128 err = s->ops->truncate(&s->ctx, path->data, size); 129 if (err < 0) { 130 err = -errno; 131 } 132 }); 133 qemu_co_rwlock_unlock(&s->rename_lock); 134 return err; 135 } 136 137 int v9fs_co_mknod(V9fsState *s, V9fsFidState *fidp, V9fsString *name, uid_t uid, 138 gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf) 139 { 140 int err; 141 FsCred cred; 142 V9fsString fullname; 143 144 cred_init(&cred); 145 cred.fc_uid = uid; 146 cred.fc_gid = gid; 147 cred.fc_mode = mode; 148 cred.fc_rdev = dev; 149 v9fs_string_init(&fullname); 150 qemu_co_rwlock_rdlock(&s->rename_lock); 151 v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data); 152 v9fs_co_run_in_worker( 153 { 154 err = s->ops->mknod(&s->ctx, fullname.data, &cred); 155 if (err < 0) { 156 err = -errno; 157 } else { 158 err = s->ops->lstat(&s->ctx, fullname.data, stbuf); 159 if (err < 0) { 160 err = -errno; 161 } 162 } 163 }); 164 qemu_co_rwlock_unlock(&s->rename_lock); 165 v9fs_string_free(&fullname); 166 return err; 167 } 168 169 int v9fs_co_remove(V9fsState *s, V9fsString *path) 170 { 171 int err; 172 173 qemu_co_rwlock_rdlock(&s->rename_lock); 174 v9fs_co_run_in_worker( 175 { 176 err = s->ops->remove(&s->ctx, path->data); 177 if (err < 0) { 178 err = -errno; 179 } 180 }); 181 qemu_co_rwlock_unlock(&s->rename_lock); 182 return err; 183 } 184 185 int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) 186 { 187 int err; 188 189 v9fs_co_run_in_worker( 190 { 191 err = s->ops->rename(&s->ctx, oldpath->data, newpath->data); 192 if (err < 0) { 193 err = -errno; 194 } 195 }); 196 return err; 197 } 198 199 int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name, 200 const char *oldpath, gid_t gid, struct stat *stbuf) 201 { 202 int err; 203 FsCred cred; 204 V9fsString fullname; 205 206 207 cred_init(&cred); 208 cred.fc_uid = dfidp->uid; 209 cred.fc_gid = gid; 210 cred.fc_mode = 0777; 211 v9fs_string_init(&fullname); 212 qemu_co_rwlock_rdlock(&s->rename_lock); 213 v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name->data); 214 v9fs_co_run_in_worker( 215 { 216 err = s->ops->symlink(&s->ctx, oldpath, fullname.data, &cred); 217 if (err < 0) { 218 err = -errno; 219 } else { 220 err = s->ops->lstat(&s->ctx, fullname.data, stbuf); 221 if (err < 0) { 222 err = -errno; 223 } 224 } 225 }); 226 qemu_co_rwlock_unlock(&s->rename_lock); 227 v9fs_string_free(&fullname); 228 return err; 229 } 230