1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include "qemu/osdep.h"
16#include "fsdev/qemu-fsdev.h"
17#include "qemu/thread.h"
18#include "qemu/coroutine.h"
19#include "coth.h"
20
21int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
22 V9fsStatDotl *v9stat)
23{
24 int err = 0;
25 V9fsState *s = pdu->s;
26
27 if (v9fs_request_cancelled(pdu)) {
28 return -EINTR;
29 }
30 if (s->ctx.exops.get_st_gen) {
31 v9fs_path_read_lock(s);
32 v9fs_co_run_in_worker(
33 {
34 err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
35 &v9stat->st_gen);
36 if (err < 0) {
37 err = -errno;
38 }
39 });
40 v9fs_path_unlock(s);
41 }
42 return err;
43}
44
45int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
46{
47 int err;
48 V9fsState *s = pdu->s;
49
50 if (v9fs_request_cancelled(pdu)) {
51 return -EINTR;
52 }
53 v9fs_path_read_lock(s);
54 v9fs_co_run_in_worker(
55 {
56 err = s->ops->lstat(&s->ctx, path, stbuf);
57 if (err < 0) {
58 err = -errno;
59 }
60 });
61 v9fs_path_unlock(s);
62 return err;
63}
64
65int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
66{
67 int err;
68 V9fsState *s = pdu->s;
69
70 if (v9fs_request_cancelled(pdu)) {
71 return -EINTR;
72 }
73 v9fs_co_run_in_worker(
74 {
75 err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
76 if (err < 0) {
77 err = -errno;
78 }
79 });
80
81
82
83
84 if (err == -EOPNOTSUPP) {
85 err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
86 if (err == -ENOENT) {
87
88
89
90
91 err = 0;
92 }
93 }
94 return err;
95}
96
97int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
98{
99 int err;
100 V9fsState *s = pdu->s;
101
102 if (v9fs_request_cancelled(pdu)) {
103 return -EINTR;
104 }
105 v9fs_path_read_lock(s);
106 v9fs_co_run_in_worker(
107 {
108 err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
109 if (err == -1) {
110 err = -errno;
111 } else {
112 err = 0;
113 }
114 });
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);
120 }
121 }
122 return err;
123}
124
125int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid,
126 int flags, int mode, struct stat *stbuf)
127{
128 int err;
129 FsCred cred;
130 V9fsPath path;
131 V9fsState *s = pdu->s;
132
133 if (v9fs_request_cancelled(pdu)) {
134 return -EINTR;
135 }
136 cred_init(&cred);
137 cred.fc_mode = mode & 07777;
138 cred.fc_uid = fidp->uid;
139 cred.fc_gid = gid;
140
141
142
143
144
145 v9fs_path_read_lock(s);
146 v9fs_co_run_in_worker(
147 {
148 err = s->ops->open2(&s->ctx, &fidp->path,
149 name->data, flags, &cred, &fidp->fs);
150 if (err < 0) {
151 err = -errno;
152 } else {
153 v9fs_path_init(&path);
154 err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
155 if (!err) {
156 err = s->ops->lstat(&s->ctx, &path, stbuf);
157 if (err < 0) {
158 err = -errno;
159 s->ops->close(&s->ctx, &fidp->fs);
160 } else {
161 v9fs_path_copy(&fidp->path, &path);
162 }
163 } else {
164 s->ops->close(&s->ctx, &fidp->fs);
165 }
166 v9fs_path_free(&path);
167 }
168 });
169 v9fs_path_unlock(s);
170 if (!err) {
171 total_open_fd++;
172 if (total_open_fd > open_fd_hw) {
173 v9fs_reclaim_fd(pdu);
174 }
175 }
176 return err;
177}
178
179int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
180{
181 int err;
182 V9fsState *s = pdu->s;
183
184 if (v9fs_request_cancelled(pdu)) {
185 return -EINTR;
186 }
187 v9fs_co_run_in_worker(
188 {
189 err = s->ops->close(&s->ctx, fs);
190 if (err < 0) {
191 err = -errno;
192 }
193 });
194 if (!err) {
195 total_open_fd--;
196 }
197 return err;
198}
199
200int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
201{
202 int err;
203 V9fsState *s = pdu->s;
204
205 if (v9fs_request_cancelled(pdu)) {
206 return -EINTR;
207 }
208 v9fs_co_run_in_worker(
209 {
210 err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
211 if (err < 0) {
212 err = -errno;
213 }
214 });
215 return err;
216}
217
218int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
219 V9fsFidState *newdirfid, V9fsString *name)
220{
221 int err;
222 V9fsState *s = pdu->s;
223
224 if (v9fs_request_cancelled(pdu)) {
225 return -EINTR;
226 }
227 v9fs_path_read_lock(s);
228 v9fs_co_run_in_worker(
229 {
230 err = s->ops->link(&s->ctx, &oldfid->path,
231 &newdirfid->path, name->data);
232 if (err < 0) {
233 err = -errno;
234 }
235 });
236 v9fs_path_unlock(s);
237 return err;
238}
239
240int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
241 struct iovec *iov, int iovcnt, int64_t offset)
242{
243 int err;
244 V9fsState *s = pdu->s;
245
246 if (v9fs_request_cancelled(pdu)) {
247 return -EINTR;
248 }
249 v9fs_co_run_in_worker(
250 {
251 err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
252 if (err < 0) {
253 err = -errno;
254 }
255 });
256 return err;
257}
258
259int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
260 struct iovec *iov, int iovcnt, int64_t offset)
261{
262 int err;
263 V9fsState *s = pdu->s;
264
265 if (v9fs_request_cancelled(pdu)) {
266 return -EINTR;
267 }
268 v9fs_co_run_in_worker(
269 {
270 err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
271 if (err < 0) {
272 err = -errno;
273 }
274 });
275 return err;
276}
277