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.
14 #include "qemu/osdep.h"
15 #include "fsdev/qemu-fsdev.h"
16 #include "qemu/thread.h"
17 #include "qemu/coroutine.h"
18 #include "qemu/main-loop.h"
21 static ssize_t
__readlink(V9fsState
*s
, V9fsPath
*path
, V9fsString
*buf
)
23 ssize_t len
, maxlen
= PATH_MAX
;
25 buf
->data
= g_malloc(PATH_MAX
);
27 len
= s
->ops
->readlink(&s
->ctx
, path
, buf
->data
, maxlen
);
33 } else if (len
== maxlen
) {
35 * We dodn't have space to put the NULL or we have more
36 * to read. Increase the size and try again
40 buf
->data
= g_malloc(maxlen
);
44 * Null terminate the readlink output
46 buf
->data
[len
] = '\0';
53 int coroutine_fn
v9fs_co_readlink(V9fsPDU
*pdu
, V9fsPath
*path
, V9fsString
*buf
)
56 V9fsState
*s
= pdu
->s
;
58 if (v9fs_request_cancelled(pdu
)) {
61 v9fs_path_read_lock(s
);
62 v9fs_co_run_in_worker(
64 err
= __readlink(s
, path
, buf
);
73 int coroutine_fn
v9fs_co_statfs(V9fsPDU
*pdu
, V9fsPath
*path
,
77 V9fsState
*s
= pdu
->s
;
79 if (v9fs_request_cancelled(pdu
)) {
82 v9fs_path_read_lock(s
);
83 v9fs_co_run_in_worker(
85 err
= s
->ops
->statfs(&s
->ctx
, path
, stbuf
);
94 int coroutine_fn
v9fs_co_chmod(V9fsPDU
*pdu
, V9fsPath
*path
, mode_t mode
)
98 V9fsState
*s
= pdu
->s
;
100 if (v9fs_request_cancelled(pdu
)) {
105 v9fs_path_read_lock(s
);
106 v9fs_co_run_in_worker(
108 err
= s
->ops
->chmod(&s
->ctx
, path
, &cred
);
117 int coroutine_fn
v9fs_co_utimensat(V9fsPDU
*pdu
, V9fsPath
*path
,
118 struct timespec times
[2])
121 V9fsState
*s
= pdu
->s
;
123 if (v9fs_request_cancelled(pdu
)) {
126 v9fs_path_read_lock(s
);
127 v9fs_co_run_in_worker(
129 err
= s
->ops
->utimensat(&s
->ctx
, path
, times
);
138 int coroutine_fn
v9fs_co_chown(V9fsPDU
*pdu
, V9fsPath
*path
, uid_t uid
,
143 V9fsState
*s
= pdu
->s
;
145 if (v9fs_request_cancelled(pdu
)) {
151 v9fs_path_read_lock(s
);
152 v9fs_co_run_in_worker(
154 err
= s
->ops
->chown(&s
->ctx
, path
, &cred
);
163 int coroutine_fn
v9fs_co_truncate(V9fsPDU
*pdu
, V9fsPath
*path
, off_t size
)
166 V9fsState
*s
= pdu
->s
;
168 if (v9fs_request_cancelled(pdu
)) {
171 v9fs_path_read_lock(s
);
172 v9fs_co_run_in_worker(
174 err
= s
->ops
->truncate(&s
->ctx
, path
, size
);
183 int coroutine_fn
v9fs_co_mknod(V9fsPDU
*pdu
, V9fsFidState
*fidp
,
184 V9fsString
*name
, uid_t uid
, gid_t gid
,
185 dev_t dev
, mode_t mode
, struct stat
*stbuf
)
190 V9fsState
*s
= pdu
->s
;
192 if (v9fs_request_cancelled(pdu
)) {
200 v9fs_path_read_lock(s
);
201 v9fs_co_run_in_worker(
203 err
= s
->ops
->mknod(&s
->ctx
, &fidp
->path
, name
->data
, &cred
);
207 v9fs_path_init(&path
);
208 err
= v9fs_name_to_path(s
, &fidp
->path
, name
->data
, &path
);
210 err
= s
->ops
->lstat(&s
->ctx
, &path
, stbuf
);
215 v9fs_path_free(&path
);
222 /* Only works with path name based fid */
223 int coroutine_fn
v9fs_co_remove(V9fsPDU
*pdu
, V9fsPath
*path
)
226 V9fsState
*s
= pdu
->s
;
228 if (v9fs_request_cancelled(pdu
)) {
231 v9fs_path_read_lock(s
);
232 v9fs_co_run_in_worker(
234 err
= s
->ops
->remove(&s
->ctx
, path
->data
);
243 int coroutine_fn
v9fs_co_unlinkat(V9fsPDU
*pdu
, V9fsPath
*path
,
244 V9fsString
*name
, int flags
)
247 V9fsState
*s
= pdu
->s
;
249 if (v9fs_request_cancelled(pdu
)) {
252 v9fs_path_read_lock(s
);
253 v9fs_co_run_in_worker(
255 err
= s
->ops
->unlinkat(&s
->ctx
, path
, name
->data
, flags
);
264 /* Only work with path name based fid */
265 int coroutine_fn
v9fs_co_rename(V9fsPDU
*pdu
, V9fsPath
*oldpath
,
269 V9fsState
*s
= pdu
->s
;
271 if (v9fs_request_cancelled(pdu
)) {
274 v9fs_co_run_in_worker(
276 err
= s
->ops
->rename(&s
->ctx
, oldpath
->data
, newpath
->data
);
284 int coroutine_fn
v9fs_co_renameat(V9fsPDU
*pdu
, V9fsPath
*olddirpath
,
285 V9fsString
*oldname
, V9fsPath
*newdirpath
,
289 V9fsState
*s
= pdu
->s
;
291 if (v9fs_request_cancelled(pdu
)) {
294 v9fs_co_run_in_worker(
296 err
= s
->ops
->renameat(&s
->ctx
, olddirpath
, oldname
->data
,
297 newdirpath
, newname
->data
);
305 int coroutine_fn
v9fs_co_symlink(V9fsPDU
*pdu
, V9fsFidState
*dfidp
,
306 V9fsString
*name
, const char *oldpath
,
307 gid_t gid
, struct stat
*stbuf
)
312 V9fsState
*s
= pdu
->s
;
314 if (v9fs_request_cancelled(pdu
)) {
318 cred
.fc_uid
= dfidp
->uid
;
321 v9fs_path_read_lock(s
);
322 v9fs_co_run_in_worker(
324 err
= s
->ops
->symlink(&s
->ctx
, oldpath
, &dfidp
->path
,
329 v9fs_path_init(&path
);
330 err
= v9fs_name_to_path(s
, &dfidp
->path
, name
->data
, &path
);
332 err
= s
->ops
->lstat(&s
->ctx
, &path
, stbuf
);
337 v9fs_path_free(&path
);
345 * For path name based fid we don't block. So we can
346 * directly call the fs driver ops.
348 int coroutine_fn
v9fs_co_name_to_path(V9fsPDU
*pdu
, V9fsPath
*dirpath
,
349 const char *name
, V9fsPath
*path
)
352 V9fsState
*s
= pdu
->s
;
354 if (s
->ctx
.export_flags
& V9FS_PATHNAME_FSCONTEXT
) {
355 err
= s
->ops
->name_to_path(&s
->ctx
, dirpath
, name
, path
);
360 if (v9fs_request_cancelled(pdu
)) {
363 v9fs_co_run_in_worker(
365 err
= s
->ops
->name_to_path(&s
->ctx
, dirpath
, name
, path
);