4 * Copyright IBM, Corp. 2011
7 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
15 * Not so fast! You might want to read the 9p developer docs first:
16 * https://wiki.qemu.org/Documentation/9p
19 #include "qemu/osdep.h"
20 #include "fsdev/qemu-fsdev.h"
21 #include "qemu/thread.h"
22 #include "qemu/coroutine.h"
23 #include "qemu/main-loop.h"
26 static ssize_t
__readlink(V9fsState
*s
, V9fsPath
*path
, V9fsString
*buf
)
28 ssize_t len
, maxlen
= PATH_MAX
;
30 buf
->data
= g_malloc(PATH_MAX
);
32 len
= s
->ops
->readlink(&s
->ctx
, path
, buf
->data
, maxlen
);
38 } else if (len
== maxlen
) {
40 * We dodn't have space to put the NULL or we have more
41 * to read. Increase the size and try again
45 buf
->data
= g_malloc(maxlen
);
49 * Null terminate the readlink output
51 buf
->data
[len
] = '\0';
58 int coroutine_fn
v9fs_co_readlink(V9fsPDU
*pdu
, V9fsPath
*path
, V9fsString
*buf
)
61 V9fsState
*s
= pdu
->s
;
63 if (v9fs_request_cancelled(pdu
)) {
66 v9fs_path_read_lock(s
);
67 v9fs_co_run_in_worker(
69 err
= __readlink(s
, path
, buf
);
78 int coroutine_fn
v9fs_co_statfs(V9fsPDU
*pdu
, V9fsPath
*path
,
82 V9fsState
*s
= pdu
->s
;
84 if (v9fs_request_cancelled(pdu
)) {
87 v9fs_path_read_lock(s
);
88 v9fs_co_run_in_worker(
90 err
= s
->ops
->statfs(&s
->ctx
, path
, stbuf
);
99 int coroutine_fn
v9fs_co_chmod(V9fsPDU
*pdu
, V9fsPath
*path
, mode_t mode
)
103 V9fsState
*s
= pdu
->s
;
105 if (v9fs_request_cancelled(pdu
)) {
110 v9fs_path_read_lock(s
);
111 v9fs_co_run_in_worker(
113 err
= s
->ops
->chmod(&s
->ctx
, path
, &cred
);
122 int coroutine_fn
v9fs_co_utimensat(V9fsPDU
*pdu
, V9fsPath
*path
,
123 struct timespec times
[2])
126 V9fsState
*s
= pdu
->s
;
128 if (v9fs_request_cancelled(pdu
)) {
131 v9fs_path_read_lock(s
);
132 v9fs_co_run_in_worker(
134 err
= s
->ops
->utimensat(&s
->ctx
, path
, times
);
143 int coroutine_fn
v9fs_co_chown(V9fsPDU
*pdu
, V9fsPath
*path
, uid_t uid
,
148 V9fsState
*s
= pdu
->s
;
150 if (v9fs_request_cancelled(pdu
)) {
156 v9fs_path_read_lock(s
);
157 v9fs_co_run_in_worker(
159 err
= s
->ops
->chown(&s
->ctx
, path
, &cred
);
168 int coroutine_fn
v9fs_co_truncate(V9fsPDU
*pdu
, V9fsPath
*path
, off_t size
)
171 V9fsState
*s
= pdu
->s
;
173 if (v9fs_request_cancelled(pdu
)) {
176 v9fs_path_read_lock(s
);
177 v9fs_co_run_in_worker(
179 err
= s
->ops
->truncate(&s
->ctx
, path
, size
);
188 int coroutine_fn
v9fs_co_mknod(V9fsPDU
*pdu
, V9fsFidState
*fidp
,
189 V9fsString
*name
, uid_t uid
, gid_t gid
,
190 dev_t dev
, mode_t mode
, struct stat
*stbuf
)
195 V9fsState
*s
= pdu
->s
;
197 if (v9fs_request_cancelled(pdu
)) {
205 v9fs_path_read_lock(s
);
206 v9fs_co_run_in_worker(
208 err
= s
->ops
->mknod(&s
->ctx
, &fidp
->path
, name
->data
, &cred
);
212 v9fs_path_init(&path
);
213 err
= v9fs_name_to_path(s
, &fidp
->path
, name
->data
, &path
);
215 err
= s
->ops
->lstat(&s
->ctx
, &path
, stbuf
);
220 v9fs_path_free(&path
);
227 /* Only works with path name based fid */
228 int coroutine_fn
v9fs_co_remove(V9fsPDU
*pdu
, V9fsPath
*path
)
231 V9fsState
*s
= pdu
->s
;
233 if (v9fs_request_cancelled(pdu
)) {
236 v9fs_path_read_lock(s
);
237 v9fs_co_run_in_worker(
239 err
= s
->ops
->remove(&s
->ctx
, path
->data
);
248 int coroutine_fn
v9fs_co_unlinkat(V9fsPDU
*pdu
, V9fsPath
*path
,
249 V9fsString
*name
, int flags
)
252 V9fsState
*s
= pdu
->s
;
254 if (v9fs_request_cancelled(pdu
)) {
257 v9fs_path_read_lock(s
);
258 v9fs_co_run_in_worker(
260 err
= s
->ops
->unlinkat(&s
->ctx
, path
, name
->data
, flags
);
269 /* Only work with path name based fid */
270 int coroutine_fn
v9fs_co_rename(V9fsPDU
*pdu
, V9fsPath
*oldpath
,
274 V9fsState
*s
= pdu
->s
;
276 if (v9fs_request_cancelled(pdu
)) {
279 v9fs_co_run_in_worker(
281 err
= s
->ops
->rename(&s
->ctx
, oldpath
->data
, newpath
->data
);
289 int coroutine_fn
v9fs_co_renameat(V9fsPDU
*pdu
, V9fsPath
*olddirpath
,
290 V9fsString
*oldname
, V9fsPath
*newdirpath
,
294 V9fsState
*s
= pdu
->s
;
296 if (v9fs_request_cancelled(pdu
)) {
299 v9fs_co_run_in_worker(
301 err
= s
->ops
->renameat(&s
->ctx
, olddirpath
, oldname
->data
,
302 newdirpath
, newname
->data
);
310 int coroutine_fn
v9fs_co_symlink(V9fsPDU
*pdu
, V9fsFidState
*dfidp
,
311 V9fsString
*name
, const char *oldpath
,
312 gid_t gid
, struct stat
*stbuf
)
317 V9fsState
*s
= pdu
->s
;
319 if (v9fs_request_cancelled(pdu
)) {
323 cred
.fc_uid
= dfidp
->uid
;
326 v9fs_path_read_lock(s
);
327 v9fs_co_run_in_worker(
329 err
= s
->ops
->symlink(&s
->ctx
, oldpath
, &dfidp
->path
,
334 v9fs_path_init(&path
);
335 err
= v9fs_name_to_path(s
, &dfidp
->path
, name
->data
, &path
);
337 err
= s
->ops
->lstat(&s
->ctx
, &path
, stbuf
);
342 v9fs_path_free(&path
);
350 * For path name based fid we don't block. So we can
351 * directly call the fs driver ops.
353 int coroutine_fn
v9fs_co_name_to_path(V9fsPDU
*pdu
, V9fsPath
*dirpath
,
354 const char *name
, V9fsPath
*path
)
357 V9fsState
*s
= pdu
->s
;
359 if (s
->ctx
.export_flags
& V9FS_PATHNAME_FSCONTEXT
) {
360 err
= s
->ops
->name_to_path(&s
->ctx
, dirpath
, name
, path
);
365 if (v9fs_request_cancelled(pdu
)) {
368 v9fs_co_run_in_worker(
370 err
= s
->ops
->name_to_path(&s
->ctx
, dirpath
, name
, path
);