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 int coroutine_fn
v9fs_co_st_gen(V9fsPDU
*pdu
, V9fsPath
*path
, mode_t st_mode
,
30 V9fsState
*s
= pdu
->s
;
32 if (v9fs_request_cancelled(pdu
)) {
35 if (s
->ctx
.exops
.get_st_gen
) {
36 v9fs_path_read_lock(s
);
37 v9fs_co_run_in_worker(
39 err
= s
->ctx
.exops
.get_st_gen(&s
->ctx
, path
, st_mode
,
50 int coroutine_fn
v9fs_co_lstat(V9fsPDU
*pdu
, V9fsPath
*path
, struct stat
*stbuf
)
53 V9fsState
*s
= pdu
->s
;
55 if (v9fs_request_cancelled(pdu
)) {
58 v9fs_path_read_lock(s
);
59 v9fs_co_run_in_worker(
61 err
= s
->ops
->lstat(&s
->ctx
, path
, stbuf
);
70 int coroutine_fn
v9fs_co_fstat(V9fsPDU
*pdu
, V9fsFidState
*fidp
,
74 V9fsState
*s
= pdu
->s
;
76 if (v9fs_request_cancelled(pdu
)) {
79 v9fs_co_run_in_worker(
81 err
= s
->ops
->fstat(&s
->ctx
, fidp
->fid_type
, &fidp
->fs
, stbuf
);
87 * Some FS driver (local:mapped-file) can't support fetching attributes
88 * using file descriptor. Use Path name in that case.
90 if (err
== -EOPNOTSUPP
) {
91 err
= v9fs_co_lstat(pdu
, &fidp
->path
, stbuf
);
94 * fstat on an unlinked file. Work with partial results
95 * returned from s->ops->fstat
103 int coroutine_fn
v9fs_co_open(V9fsPDU
*pdu
, V9fsFidState
*fidp
, int flags
)
106 V9fsState
*s
= pdu
->s
;
108 if (v9fs_request_cancelled(pdu
)) {
111 v9fs_path_read_lock(s
);
112 v9fs_co_run_in_worker(
114 err
= s
->ops
->open(&s
->ctx
, &fidp
->path
, flags
, &fidp
->fs
);
124 if (total_open_fd
> open_fd_hw
) {
125 v9fs_reclaim_fd(pdu
);
131 int coroutine_fn
v9fs_co_open2(V9fsPDU
*pdu
, V9fsFidState
*fidp
,
132 V9fsString
*name
, gid_t gid
, int flags
, int mode
,
138 V9fsState
*s
= pdu
->s
;
140 if (v9fs_request_cancelled(pdu
)) {
144 cred
.fc_mode
= mode
& 07777;
145 cred
.fc_uid
= fidp
->uid
;
148 * Hold the directory fid lock so that directory path name
149 * don't change. Take the write lock to be sure this fid
150 * cannot be used by another operation.
152 v9fs_path_write_lock(s
);
153 v9fs_co_run_in_worker(
155 err
= s
->ops
->open2(&s
->ctx
, &fidp
->path
,
156 name
->data
, flags
, &cred
, &fidp
->fs
);
160 v9fs_path_init(&path
);
161 err
= v9fs_name_to_path(s
, &fidp
->path
, name
->data
, &path
);
163 err
= s
->ops
->lstat(&s
->ctx
, &path
, stbuf
);
166 s
->ops
->close(&s
->ctx
, &fidp
->fs
);
168 v9fs_path_copy(&fidp
->path
, &path
);
171 s
->ops
->close(&s
->ctx
, &fidp
->fs
);
173 v9fs_path_free(&path
);
179 if (total_open_fd
> open_fd_hw
) {
180 v9fs_reclaim_fd(pdu
);
186 int coroutine_fn
v9fs_co_close(V9fsPDU
*pdu
, V9fsFidOpenState
*fs
)
189 V9fsState
*s
= pdu
->s
;
191 if (v9fs_request_cancelled(pdu
)) {
194 v9fs_co_run_in_worker(
196 err
= s
->ops
->close(&s
->ctx
, fs
);
207 int coroutine_fn
v9fs_co_fsync(V9fsPDU
*pdu
, V9fsFidState
*fidp
, int datasync
)
210 V9fsState
*s
= pdu
->s
;
212 if (v9fs_request_cancelled(pdu
)) {
215 v9fs_co_run_in_worker(
217 err
= s
->ops
->fsync(&s
->ctx
, fidp
->fid_type
, &fidp
->fs
, datasync
);
225 int coroutine_fn
v9fs_co_link(V9fsPDU
*pdu
, V9fsFidState
*oldfid
,
226 V9fsFidState
*newdirfid
, V9fsString
*name
)
229 V9fsState
*s
= pdu
->s
;
231 if (v9fs_request_cancelled(pdu
)) {
234 v9fs_path_read_lock(s
);
235 v9fs_co_run_in_worker(
237 err
= s
->ops
->link(&s
->ctx
, &oldfid
->path
,
238 &newdirfid
->path
, name
->data
);
247 int coroutine_fn
v9fs_co_pwritev(V9fsPDU
*pdu
, V9fsFidState
*fidp
,
248 struct iovec
*iov
, int iovcnt
, int64_t offset
)
251 V9fsState
*s
= pdu
->s
;
253 if (v9fs_request_cancelled(pdu
)) {
256 fsdev_co_throttle_request(s
->ctx
.fst
, true, iov
, iovcnt
);
257 v9fs_co_run_in_worker(
259 err
= s
->ops
->pwritev(&s
->ctx
, &fidp
->fs
, iov
, iovcnt
, offset
);
267 int coroutine_fn
v9fs_co_preadv(V9fsPDU
*pdu
, V9fsFidState
*fidp
,
268 struct iovec
*iov
, int iovcnt
, int64_t offset
)
271 V9fsState
*s
= pdu
->s
;
273 if (v9fs_request_cancelled(pdu
)) {
276 fsdev_co_throttle_request(s
->ctx
.fst
, false, iov
, iovcnt
);
277 v9fs_co_run_in_worker(
279 err
= s
->ops
->preadv(&s
->ctx
, &fidp
->fs
, iov
, iovcnt
, offset
);