]>
Commit | Line | Data |
---|---|---|
172198d4 | 1 | /* |
af8b38b0 | 2 | * 9p backend |
172198d4 AK |
3 | * |
4 | * Copyright IBM, Corp. 2011 | |
5 | * | |
6 | * Authors: | |
7 | * Aneesh Kumar K.V <[email protected]> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | * | |
12 | */ | |
13 | ||
fbc04127 | 14 | #include "qemu/osdep.h" |
172198d4 | 15 | #include "fsdev/qemu-fsdev.h" |
1de7afc9 | 16 | #include "qemu/thread.h" |
10817bf0 | 17 | #include "qemu/coroutine.h" |
db725815 | 18 | #include "qemu/main-loop.h" |
fe52840c | 19 | #include "coth.h" |
172198d4 | 20 | |
5bdade66 GK |
21 | int coroutine_fn v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, |
22 | V9fsStatDotl *v9stat) | |
e06a765e HPB |
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 | ||
5bdade66 | 45 | int coroutine_fn v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) |
172198d4 AK |
46 | { |
47 | int err; | |
bccacf6c | 48 | V9fsState *s = pdu->s; |
172198d4 | 49 | |
bccacf6c AK |
50 | if (v9fs_request_cancelled(pdu)) { |
51 | return -EINTR; | |
52 | } | |
532decb7 | 53 | v9fs_path_read_lock(s); |
172198d4 AK |
54 | v9fs_co_run_in_worker( |
55 | { | |
2289be19 | 56 | err = s->ops->lstat(&s->ctx, path, stbuf); |
172198d4 AK |
57 | if (err < 0) { |
58 | err = -errno; | |
59 | } | |
60 | }); | |
532decb7 | 61 | v9fs_path_unlock(s); |
172198d4 AK |
62 | return err; |
63 | } | |
03feb1e1 | 64 | |
5bdade66 GK |
65 | int coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, |
66 | struct stat *stbuf) | |
03feb1e1 AK |
67 | { |
68 | int err; | |
bccacf6c | 69 | V9fsState *s = pdu->s; |
03feb1e1 | 70 | |
bccacf6c AK |
71 | if (v9fs_request_cancelled(pdu)) { |
72 | return -EINTR; | |
73 | } | |
03feb1e1 AK |
74 | v9fs_co_run_in_worker( |
75 | { | |
8b888272 | 76 | err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf); |
03feb1e1 AK |
77 | if (err < 0) { |
78 | err = -errno; | |
79 | } | |
80 | }); | |
2c30dd74 AK |
81 | /* |
82 | * Some FS driver (local:mapped-file) can't support fetching attributes | |
83 | * using file descriptor. Use Path name in that case. | |
84 | */ | |
85 | if (err == -EOPNOTSUPP) { | |
86 | err = v9fs_co_lstat(pdu, &fidp->path, stbuf); | |
87 | if (err == -ENOENT) { | |
88 | /* | |
89 | * fstat on an unlinked file. Work with partial results | |
90 | * returned from s->ops->fstat | |
91 | */ | |
92 | err = 0; | |
93 | } | |
94 | } | |
03feb1e1 AK |
95 | return err; |
96 | } | |
f6b7f0ab | 97 | |
5bdade66 | 98 | int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) |
f6b7f0ab AK |
99 | { |
100 | int err; | |
bccacf6c | 101 | V9fsState *s = pdu->s; |
f6b7f0ab | 102 | |
bccacf6c AK |
103 | if (v9fs_request_cancelled(pdu)) { |
104 | return -EINTR; | |
105 | } | |
532decb7 | 106 | v9fs_path_read_lock(s); |
f6b7f0ab AK |
107 | v9fs_co_run_in_worker( |
108 | { | |
cc720ddb AK |
109 | err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs); |
110 | if (err == -1) { | |
f6b7f0ab AK |
111 | err = -errno; |
112 | } else { | |
113 | err = 0; | |
114 | } | |
115 | }); | |
532decb7 | 116 | v9fs_path_unlock(s); |
7a462745 AK |
117 | if (!err) { |
118 | total_open_fd++; | |
119 | if (total_open_fd > open_fd_hw) { | |
bccacf6c | 120 | v9fs_reclaim_fd(pdu); |
7a462745 AK |
121 | } |
122 | } | |
f6b7f0ab AK |
123 | return err; |
124 | } | |
e4de4232 | 125 | |
5bdade66 GK |
126 | int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, |
127 | V9fsString *name, gid_t gid, int flags, int mode, | |
128 | struct stat *stbuf) | |
e4de4232 VJ |
129 | { |
130 | int err; | |
131 | FsCred cred; | |
2289be19 | 132 | V9fsPath path; |
bccacf6c | 133 | V9fsState *s = pdu->s; |
2289be19 | 134 | |
bccacf6c AK |
135 | if (v9fs_request_cancelled(pdu)) { |
136 | return -EINTR; | |
137 | } | |
e4de4232 VJ |
138 | cred_init(&cred); |
139 | cred.fc_mode = mode & 07777; | |
140 | cred.fc_uid = fidp->uid; | |
141 | cred.fc_gid = gid; | |
02cb7f3a AK |
142 | /* |
143 | * Hold the directory fid lock so that directory path name | |
5b76ef50 GK |
144 | * don't change. Take the write lock to be sure this fid |
145 | * cannot be used by another operation. | |
02cb7f3a | 146 | */ |
5b76ef50 | 147 | v9fs_path_write_lock(s); |
e4de4232 VJ |
148 | v9fs_co_run_in_worker( |
149 | { | |
cc720ddb AK |
150 | err = s->ops->open2(&s->ctx, &fidp->path, |
151 | name->data, flags, &cred, &fidp->fs); | |
152 | if (err < 0) { | |
e4de4232 | 153 | err = -errno; |
02cb7f3a | 154 | } else { |
2289be19 AK |
155 | v9fs_path_init(&path); |
156 | err = v9fs_name_to_path(s, &fidp->path, name->data, &path); | |
157 | if (!err) { | |
158 | err = s->ops->lstat(&s->ctx, &path, stbuf); | |
159 | if (err < 0) { | |
160 | err = -errno; | |
cc720ddb | 161 | s->ops->close(&s->ctx, &fidp->fs); |
2289be19 AK |
162 | } else { |
163 | v9fs_path_copy(&fidp->path, &path); | |
164 | } | |
02cb7f3a | 165 | } else { |
cc720ddb | 166 | s->ops->close(&s->ctx, &fidp->fs); |
02cb7f3a | 167 | } |
2289be19 | 168 | v9fs_path_free(&path); |
e4de4232 VJ |
169 | } |
170 | }); | |
532decb7 | 171 | v9fs_path_unlock(s); |
7a462745 AK |
172 | if (!err) { |
173 | total_open_fd++; | |
174 | if (total_open_fd > open_fd_hw) { | |
bccacf6c | 175 | v9fs_reclaim_fd(pdu); |
7a462745 AK |
176 | } |
177 | } | |
e4de4232 VJ |
178 | return err; |
179 | } | |
bed4352c | 180 | |
5bdade66 | 181 | int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs) |
bed4352c | 182 | { |
bed4352c | 183 | int err; |
bccacf6c | 184 | V9fsState *s = pdu->s; |
bed4352c | 185 | |
bccacf6c AK |
186 | if (v9fs_request_cancelled(pdu)) { |
187 | return -EINTR; | |
188 | } | |
bed4352c AK |
189 | v9fs_co_run_in_worker( |
190 | { | |
cc720ddb | 191 | err = s->ops->close(&s->ctx, fs); |
bed4352c AK |
192 | if (err < 0) { |
193 | err = -errno; | |
194 | } | |
195 | }); | |
7a462745 AK |
196 | if (!err) { |
197 | total_open_fd--; | |
198 | } | |
bed4352c AK |
199 | return err; |
200 | } | |
4743d1f5 | 201 | |
5bdade66 | 202 | int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) |
4743d1f5 | 203 | { |
cc720ddb | 204 | int err; |
bccacf6c | 205 | V9fsState *s = pdu->s; |
4743d1f5 | 206 | |
bccacf6c AK |
207 | if (v9fs_request_cancelled(pdu)) { |
208 | return -EINTR; | |
209 | } | |
4743d1f5 AK |
210 | v9fs_co_run_in_worker( |
211 | { | |
8b888272 | 212 | err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync); |
4743d1f5 AK |
213 | if (err < 0) { |
214 | err = -errno; | |
215 | } | |
216 | }); | |
217 | return err; | |
218 | } | |
c6c069b0 | 219 | |
5bdade66 GK |
220 | int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, |
221 | V9fsFidState *newdirfid, V9fsString *name) | |
c6c069b0 VJ |
222 | { |
223 | int err; | |
bccacf6c | 224 | V9fsState *s = pdu->s; |
c6c069b0 | 225 | |
bccacf6c AK |
226 | if (v9fs_request_cancelled(pdu)) { |
227 | return -EINTR; | |
228 | } | |
532decb7 | 229 | v9fs_path_read_lock(s); |
c6c069b0 VJ |
230 | v9fs_co_run_in_worker( |
231 | { | |
2289be19 AK |
232 | err = s->ops->link(&s->ctx, &oldfid->path, |
233 | &newdirfid->path, name->data); | |
c6c069b0 VJ |
234 | if (err < 0) { |
235 | err = -errno; | |
236 | } | |
237 | }); | |
532decb7 | 238 | v9fs_path_unlock(s); |
c6c069b0 VJ |
239 | return err; |
240 | } | |
f6b3c976 | 241 | |
5bdade66 GK |
242 | int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, |
243 | struct iovec *iov, int iovcnt, int64_t offset) | |
f6b3c976 | 244 | { |
cc720ddb | 245 | int err; |
bccacf6c | 246 | V9fsState *s = pdu->s; |
f6b3c976 | 247 | |
bccacf6c AK |
248 | if (v9fs_request_cancelled(pdu)) { |
249 | return -EINTR; | |
250 | } | |
b8bbdb88 | 251 | fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt); |
f6b3c976 AK |
252 | v9fs_co_run_in_worker( |
253 | { | |
cc720ddb | 254 | err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset); |
f6b3c976 AK |
255 | if (err < 0) { |
256 | err = -errno; | |
257 | } | |
258 | }); | |
259 | return err; | |
260 | } | |
7eafdcc9 | 261 | |
5bdade66 GK |
262 | int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, |
263 | struct iovec *iov, int iovcnt, int64_t offset) | |
7eafdcc9 | 264 | { |
cc720ddb | 265 | int err; |
bccacf6c | 266 | V9fsState *s = pdu->s; |
7eafdcc9 | 267 | |
bccacf6c AK |
268 | if (v9fs_request_cancelled(pdu)) { |
269 | return -EINTR; | |
270 | } | |
b8bbdb88 | 271 | fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt); |
7eafdcc9 AK |
272 | v9fs_co_run_in_worker( |
273 | { | |
cc720ddb | 274 | err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset); |
7eafdcc9 AK |
275 | if (err < 0) { |
276 | err = -errno; | |
277 | } | |
278 | }); | |
279 | return err; | |
280 | } |