cpus: make pause_all_cpus() play with SMP on single threaded TCG
[qemu/ar7.git] / hw / 9pfs / cofile.c
blob88791bc327acfe6b4591cb5d0402e51ca93feef6
1 /*
2 * 9p backend
4 * Copyright IBM, Corp. 2011
6 * Authors:
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 "coth.h"
20 int coroutine_fn v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
21 V9fsStatDotl *v9stat)
23 int err = 0;
24 V9fsState *s = pdu->s;
26 if (v9fs_request_cancelled(pdu)) {
27 return -EINTR;
29 if (s->ctx.exops.get_st_gen) {
30 v9fs_path_read_lock(s);
31 v9fs_co_run_in_worker(
33 err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
34 &v9stat->st_gen);
35 if (err < 0) {
36 err = -errno;
38 });
39 v9fs_path_unlock(s);
41 return err;
44 int coroutine_fn v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
46 int err;
47 V9fsState *s = pdu->s;
49 if (v9fs_request_cancelled(pdu)) {
50 return -EINTR;
52 v9fs_path_read_lock(s);
53 v9fs_co_run_in_worker(
55 err = s->ops->lstat(&s->ctx, path, stbuf);
56 if (err < 0) {
57 err = -errno;
59 });
60 v9fs_path_unlock(s);
61 return err;
64 int coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp,
65 struct stat *stbuf)
67 int err;
68 V9fsState *s = pdu->s;
70 if (v9fs_request_cancelled(pdu)) {
71 return -EINTR;
73 v9fs_co_run_in_worker(
75 err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
76 if (err < 0) {
77 err = -errno;
79 });
81 * Some FS driver (local:mapped-file) can't support fetching attributes
82 * using file descriptor. Use Path name in that case.
84 if (err == -EOPNOTSUPP) {
85 err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
86 if (err == -ENOENT) {
88 * fstat on an unlinked file. Work with partial results
89 * returned from s->ops->fstat
91 err = 0;
94 return err;
97 int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
99 int err;
100 V9fsState *s = pdu->s;
102 if (v9fs_request_cancelled(pdu)) {
103 return -EINTR;
105 v9fs_path_read_lock(s);
106 v9fs_co_run_in_worker(
108 err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
109 if (err == -1) {
110 err = -errno;
111 } else {
112 err = 0;
115 v9fs_path_unlock(s);
116 if (!err) {
117 total_open_fd++;
118 if (total_open_fd > open_fd_hw) {
119 v9fs_reclaim_fd(pdu);
122 return err;
125 int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
126 V9fsString *name, gid_t gid, int flags, int mode,
127 struct stat *stbuf)
129 int err;
130 FsCred cred;
131 V9fsPath path;
132 V9fsState *s = pdu->s;
134 if (v9fs_request_cancelled(pdu)) {
135 return -EINTR;
137 cred_init(&cred);
138 cred.fc_mode = mode & 07777;
139 cred.fc_uid = fidp->uid;
140 cred.fc_gid = gid;
142 * Hold the directory fid lock so that directory path name
143 * don't change. Read lock is fine because this fid cannot
144 * be used by any other operation.
146 v9fs_path_read_lock(s);
147 v9fs_co_run_in_worker(
149 err = s->ops->open2(&s->ctx, &fidp->path,
150 name->data, flags, &cred, &fidp->fs);
151 if (err < 0) {
152 err = -errno;
153 } else {
154 v9fs_path_init(&path);
155 err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
156 if (!err) {
157 err = s->ops->lstat(&s->ctx, &path, stbuf);
158 if (err < 0) {
159 err = -errno;
160 s->ops->close(&s->ctx, &fidp->fs);
161 } else {
162 v9fs_path_copy(&fidp->path, &path);
164 } else {
165 s->ops->close(&s->ctx, &fidp->fs);
167 v9fs_path_free(&path);
170 v9fs_path_unlock(s);
171 if (!err) {
172 total_open_fd++;
173 if (total_open_fd > open_fd_hw) {
174 v9fs_reclaim_fd(pdu);
177 return err;
180 int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
182 int err;
183 V9fsState *s = pdu->s;
185 if (v9fs_request_cancelled(pdu)) {
186 return -EINTR;
188 v9fs_co_run_in_worker(
190 err = s->ops->close(&s->ctx, fs);
191 if (err < 0) {
192 err = -errno;
195 if (!err) {
196 total_open_fd--;
198 return err;
201 int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
203 int err;
204 V9fsState *s = pdu->s;
206 if (v9fs_request_cancelled(pdu)) {
207 return -EINTR;
209 v9fs_co_run_in_worker(
211 err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
212 if (err < 0) {
213 err = -errno;
216 return err;
219 int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
220 V9fsFidState *newdirfid, V9fsString *name)
222 int err;
223 V9fsState *s = pdu->s;
225 if (v9fs_request_cancelled(pdu)) {
226 return -EINTR;
228 v9fs_path_read_lock(s);
229 v9fs_co_run_in_worker(
231 err = s->ops->link(&s->ctx, &oldfid->path,
232 &newdirfid->path, name->data);
233 if (err < 0) {
234 err = -errno;
237 v9fs_path_unlock(s);
238 return err;
241 int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
242 struct iovec *iov, int iovcnt, int64_t offset)
244 int err;
245 V9fsState *s = pdu->s;
247 if (v9fs_request_cancelled(pdu)) {
248 return -EINTR;
250 fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
251 v9fs_co_run_in_worker(
253 err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
254 if (err < 0) {
255 err = -errno;
258 return err;
261 int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
262 struct iovec *iov, int iovcnt, int64_t offset)
264 int err;
265 V9fsState *s = pdu->s;
267 if (v9fs_request_cancelled(pdu)) {
268 return -EINTR;
270 fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
271 v9fs_co_run_in_worker(
273 err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
274 if (err < 0) {
275 err = -errno;
278 return err;