]> git.proxmox.com Git - mirror_qemu.git/blame - hw/9pfs/cofs.c
vfio-pci: Fix error path sign
[mirror_qemu.git] / hw / 9pfs / cofs.c
CommitLineData
86e42d74
VJ
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"
1de7afc9 16#include "qemu/thread.h"
737e150e 17#include "block/coroutine.h"
86e42d74
VJ
18#include "virtio-9p-coth.h"
19
4fa4ce71
CG
20static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
21{
22 ssize_t len, maxlen = PATH_MAX;
23
24 buf->data = g_malloc(PATH_MAX);
25 for(;;) {
26 len = s->ops->readlink(&s->ctx, path, buf->data, maxlen);
27 if (len < 0) {
28 g_free(buf->data);
29 buf->data = NULL;
30 buf->size = 0;
31 break;
32 } else if (len == maxlen) {
33 /*
34 * We dodn't have space to put the NULL or we have more
35 * to read. Increase the size and try again
36 */
37 maxlen *= 2;
38 g_free(buf->data);
39 buf->data = g_malloc(maxlen);
40 continue;
41 }
42 /*
43 * Null terminate the readlink output
44 */
45 buf->data[len] = '\0';
46 buf->size = len;
47 break;
48 }
49 return len;
50}
51
bccacf6c 52int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
86e42d74
VJ
53{
54 int err;
bccacf6c 55 V9fsState *s = pdu->s;
86e42d74 56
bccacf6c
AK
57 if (v9fs_request_cancelled(pdu)) {
58 return -EINTR;
59 }
532decb7 60 v9fs_path_read_lock(s);
86e42d74
VJ
61 v9fs_co_run_in_worker(
62 {
4fa4ce71
CG
63 err = __readlink(s, path, buf);
64 if (err < 0) {
86e42d74
VJ
65 err = -errno;
66 }
67 });
532decb7 68 v9fs_path_unlock(s);
86e42d74
VJ
69 return err;
70}
94840ff9 71
bccacf6c 72int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, struct statfs *stbuf)
94840ff9
AK
73{
74 int err;
bccacf6c 75 V9fsState *s = pdu->s;
94840ff9 76
bccacf6c
AK
77 if (v9fs_request_cancelled(pdu)) {
78 return -EINTR;
79 }
532decb7 80 v9fs_path_read_lock(s);
94840ff9
AK
81 v9fs_co_run_in_worker(
82 {
2289be19 83 err = s->ops->statfs(&s->ctx, path, stbuf);
94840ff9
AK
84 if (err < 0) {
85 err = -errno;
86 }
87 });
532decb7 88 v9fs_path_unlock(s);
94840ff9
AK
89 return err;
90}
4011ead2 91
bccacf6c 92int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode)
4011ead2
AK
93{
94 int err;
95 FsCred cred;
bccacf6c 96 V9fsState *s = pdu->s;
4011ead2 97
bccacf6c
AK
98 if (v9fs_request_cancelled(pdu)) {
99 return -EINTR;
100 }
4011ead2
AK
101 cred_init(&cred);
102 cred.fc_mode = mode;
532decb7 103 v9fs_path_read_lock(s);
4011ead2
AK
104 v9fs_co_run_in_worker(
105 {
2289be19 106 err = s->ops->chmod(&s->ctx, path, &cred);
4011ead2
AK
107 if (err < 0) {
108 err = -errno;
109 }
110 });
532decb7 111 v9fs_path_unlock(s);
4011ead2
AK
112 return err;
113}
114
bccacf6c 115int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
4011ead2
AK
116 struct timespec times[2])
117{
118 int err;
bccacf6c 119 V9fsState *s = pdu->s;
4011ead2 120
bccacf6c
AK
121 if (v9fs_request_cancelled(pdu)) {
122 return -EINTR;
123 }
532decb7 124 v9fs_path_read_lock(s);
4011ead2
AK
125 v9fs_co_run_in_worker(
126 {
2289be19 127 err = s->ops->utimensat(&s->ctx, path, times);
4011ead2
AK
128 if (err < 0) {
129 err = -errno;
130 }
131 });
532decb7 132 v9fs_path_unlock(s);
4011ead2
AK
133 return err;
134}
135
bccacf6c 136int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid)
4011ead2
AK
137{
138 int err;
139 FsCred cred;
bccacf6c 140 V9fsState *s = pdu->s;
4011ead2 141
bccacf6c
AK
142 if (v9fs_request_cancelled(pdu)) {
143 return -EINTR;
144 }
4011ead2
AK
145 cred_init(&cred);
146 cred.fc_uid = uid;
147 cred.fc_gid = gid;
532decb7 148 v9fs_path_read_lock(s);
4011ead2
AK
149 v9fs_co_run_in_worker(
150 {
2289be19 151 err = s->ops->chown(&s->ctx, path, &cred);
4011ead2
AK
152 if (err < 0) {
153 err = -errno;
154 }
155 });
532decb7 156 v9fs_path_unlock(s);
4011ead2
AK
157 return err;
158}
159
bccacf6c 160int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size)
4011ead2
AK
161{
162 int err;
bccacf6c 163 V9fsState *s = pdu->s;
4011ead2 164
bccacf6c
AK
165 if (v9fs_request_cancelled(pdu)) {
166 return -EINTR;
167 }
532decb7 168 v9fs_path_read_lock(s);
4011ead2
AK
169 v9fs_co_run_in_worker(
170 {
2289be19 171 err = s->ops->truncate(&s->ctx, path, size);
4011ead2
AK
172 if (err < 0) {
173 err = -errno;
174 }
175 });
532decb7 176 v9fs_path_unlock(s);
4011ead2
AK
177 return err;
178}
00ace8c5 179
bccacf6c 180int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid,
02cb7f3a 181 gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
00ace8c5
AK
182{
183 int err;
2289be19 184 V9fsPath path;
00ace8c5 185 FsCred cred;
bccacf6c 186 V9fsState *s = pdu->s;
00ace8c5 187
bccacf6c
AK
188 if (v9fs_request_cancelled(pdu)) {
189 return -EINTR;
190 }
00ace8c5
AK
191 cred_init(&cred);
192 cred.fc_uid = uid;
193 cred.fc_gid = gid;
194 cred.fc_mode = mode;
195 cred.fc_rdev = dev;
532decb7 196 v9fs_path_read_lock(s);
00ace8c5
AK
197 v9fs_co_run_in_worker(
198 {
2289be19 199 err = s->ops->mknod(&s->ctx, &fidp->path, name->data, &cred);
00ace8c5
AK
200 if (err < 0) {
201 err = -errno;
02cb7f3a 202 } else {
2289be19
AK
203 v9fs_path_init(&path);
204 err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
205 if (!err) {
206 err = s->ops->lstat(&s->ctx, &path, stbuf);
207 if (err < 0) {
208 err = -errno;
209 }
02cb7f3a 210 }
2289be19 211 v9fs_path_free(&path);
00ace8c5
AK
212 }
213 });
532decb7 214 v9fs_path_unlock(s);
00ace8c5
AK
215 return err;
216}
b4b1537b 217
2289be19 218/* Only works with path name based fid */
bccacf6c 219int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path)
b4b1537b
VJ
220{
221 int err;
bccacf6c 222 V9fsState *s = pdu->s;
b4b1537b 223
bccacf6c
AK
224 if (v9fs_request_cancelled(pdu)) {
225 return -EINTR;
226 }
532decb7 227 v9fs_path_read_lock(s);
b4b1537b
VJ
228 v9fs_co_run_in_worker(
229 {
230 err = s->ops->remove(&s->ctx, path->data);
231 if (err < 0) {
232 err = -errno;
233 }
234 });
532decb7 235 v9fs_path_unlock(s);
b4b1537b
VJ
236 return err;
237}
2a487e05 238
bccacf6c 239int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9fsString *name, int flags)
2289be19
AK
240{
241 int err;
bccacf6c 242 V9fsState *s = pdu->s;
2289be19 243
bccacf6c
AK
244 if (v9fs_request_cancelled(pdu)) {
245 return -EINTR;
246 }
532decb7 247 v9fs_path_read_lock(s);
2289be19
AK
248 v9fs_co_run_in_worker(
249 {
250 err = s->ops->unlinkat(&s->ctx, path, name->data, flags);
251 if (err < 0) {
252 err = -errno;
253 }
254 });
532decb7 255 v9fs_path_unlock(s);
2289be19
AK
256 return err;
257}
258
259/* Only work with path name based fid */
bccacf6c 260int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V9fsPath *newpath)
2a487e05
AK
261{
262 int err;
bccacf6c 263 V9fsState *s = pdu->s;
2a487e05 264
bccacf6c
AK
265 if (v9fs_request_cancelled(pdu)) {
266 return -EINTR;
267 }
2a487e05
AK
268 v9fs_co_run_in_worker(
269 {
270 err = s->ops->rename(&s->ctx, oldpath->data, newpath->data);
271 if (err < 0) {
272 err = -errno;
273 }
274 });
275 return err;
276}
02ac7a34 277
bccacf6c 278int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpath, V9fsString *oldname,
2289be19
AK
279 V9fsPath *newdirpath, V9fsString *newname)
280{
281 int err;
bccacf6c 282 V9fsState *s = pdu->s;
2289be19 283
bccacf6c
AK
284 if (v9fs_request_cancelled(pdu)) {
285 return -EINTR;
286 }
2289be19
AK
287 v9fs_co_run_in_worker(
288 {
289 err = s->ops->renameat(&s->ctx, olddirpath, oldname->data,
290 newdirpath, newname->data);
291 if (err < 0) {
292 err = -errno;
293 }
294 });
295 return err;
296}
297
bccacf6c 298int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState *dfidp, V9fsString *name,
02cb7f3a 299 const char *oldpath, gid_t gid, struct stat *stbuf)
02ac7a34
VJ
300{
301 int err;
302 FsCred cred;
2289be19 303 V9fsPath path;
bccacf6c 304 V9fsState *s = pdu->s;
02cb7f3a 305
bccacf6c
AK
306 if (v9fs_request_cancelled(pdu)) {
307 return -EINTR;
308 }
02ac7a34 309 cred_init(&cred);
02cb7f3a 310 cred.fc_uid = dfidp->uid;
02ac7a34
VJ
311 cred.fc_gid = gid;
312 cred.fc_mode = 0777;
532decb7 313 v9fs_path_read_lock(s);
02ac7a34
VJ
314 v9fs_co_run_in_worker(
315 {
2289be19
AK
316 err = s->ops->symlink(&s->ctx, oldpath, &dfidp->path,
317 name->data, &cred);
02ac7a34
VJ
318 if (err < 0) {
319 err = -errno;
02cb7f3a 320 } else {
2289be19
AK
321 v9fs_path_init(&path);
322 err = v9fs_name_to_path(s, &dfidp->path, name->data, &path);
323 if (!err) {
324 err = s->ops->lstat(&s->ctx, &path, stbuf);
325 if (err < 0) {
326 err = -errno;
327 }
02cb7f3a 328 }
2289be19 329 v9fs_path_free(&path);
02ac7a34
VJ
330 }
331 });
532decb7 332 v9fs_path_unlock(s);
2289be19
AK
333 return err;
334}
335
336/*
337 * For path name based fid we don't block. So we can
338 * directly call the fs driver ops.
339 */
bccacf6c 340int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath,
2289be19
AK
341 const char *name, V9fsPath *path)
342{
343 int err;
bccacf6c 344 V9fsState *s = pdu->s;
532decb7 345
c98f1d4a 346 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
532decb7
AK
347 err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
348 if (err < 0) {
349 err = -errno;
350 }
351 } else {
bccacf6c
AK
352 if (v9fs_request_cancelled(pdu)) {
353 return -EINTR;
354 }
532decb7
AK
355 v9fs_co_run_in_worker(
356 {
357 err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
358 if (err < 0) {
359 err = -errno;
360 }
361 });
2289be19 362 }
02ac7a34
VJ
363 return err;
364}