]>
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" |
fe52840c | 18 | #include "coth.h" |
172198d4 | 19 | |
5bdade66 GK |
20 | int coroutine_fn v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, |
21 | V9fsStatDotl *v9stat) | |
e06a765e HPB |
22 | { |
23 | int err = 0; | |
24 | V9fsState *s = pdu->s; | |
25 | ||
26 | if (v9fs_request_cancelled(pdu)) { | |
27 | return -EINTR; | |
28 | } | |
29 | if (s->ctx.exops.get_st_gen) { | |
30 | v9fs_path_read_lock(s); | |
31 | v9fs_co_run_in_worker( | |
32 | { | |
33 | err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode, | |
34 | &v9stat->st_gen); | |
35 | if (err < 0) { | |
36 | err = -errno; | |
37 | } | |
38 | }); | |
39 | v9fs_path_unlock(s); | |
40 | } | |
41 | return err; | |
42 | } | |
43 | ||
5bdade66 | 44 | int coroutine_fn v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) |
172198d4 AK |
45 | { |
46 | int err; | |
bccacf6c | 47 | V9fsState *s = pdu->s; |
172198d4 | 48 | |
bccacf6c AK |
49 | if (v9fs_request_cancelled(pdu)) { |
50 | return -EINTR; | |
51 | } | |
532decb7 | 52 | v9fs_path_read_lock(s); |
172198d4 AK |
53 | v9fs_co_run_in_worker( |
54 | { | |
2289be19 | 55 | err = s->ops->lstat(&s->ctx, path, stbuf); |
172198d4 AK |
56 | if (err < 0) { |
57 | err = -errno; | |
58 | } | |
59 | }); | |
532decb7 | 60 | v9fs_path_unlock(s); |
172198d4 AK |
61 | return err; |
62 | } | |
03feb1e1 | 63 | |
5bdade66 GK |
64 | int coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, |
65 | struct stat *stbuf) | |
03feb1e1 AK |
66 | { |
67 | int err; | |
bccacf6c | 68 | V9fsState *s = pdu->s; |
03feb1e1 | 69 | |
bccacf6c AK |
70 | if (v9fs_request_cancelled(pdu)) { |
71 | return -EINTR; | |
72 | } | |
03feb1e1 AK |
73 | v9fs_co_run_in_worker( |
74 | { | |
8b888272 | 75 | err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf); |
03feb1e1 AK |
76 | if (err < 0) { |
77 | err = -errno; | |
78 | } | |
79 | }); | |
2c30dd74 AK |
80 | /* |
81 | * Some FS driver (local:mapped-file) can't support fetching attributes | |
82 | * using file descriptor. Use Path name in that case. | |
83 | */ | |
84 | if (err == -EOPNOTSUPP) { | |
85 | err = v9fs_co_lstat(pdu, &fidp->path, stbuf); | |
86 | if (err == -ENOENT) { | |
87 | /* | |
88 | * fstat on an unlinked file. Work with partial results | |
89 | * returned from s->ops->fstat | |
90 | */ | |
91 | err = 0; | |
92 | } | |
93 | } | |
03feb1e1 AK |
94 | return err; |
95 | } | |
f6b7f0ab | 96 | |
5bdade66 | 97 | int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) |
f6b7f0ab AK |
98 | { |
99 | int err; | |
bccacf6c | 100 | V9fsState *s = pdu->s; |
f6b7f0ab | 101 | |
bccacf6c AK |
102 | if (v9fs_request_cancelled(pdu)) { |
103 | return -EINTR; | |
104 | } | |
532decb7 | 105 | v9fs_path_read_lock(s); |
f6b7f0ab AK |
106 | v9fs_co_run_in_worker( |
107 | { | |
cc720ddb AK |
108 | err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs); |
109 | if (err == -1) { | |
f6b7f0ab AK |
110 | err = -errno; |
111 | } else { | |
112 | err = 0; | |
113 | } | |
114 | }); | |
532decb7 | 115 | v9fs_path_unlock(s); |
7a462745 AK |
116 | if (!err) { |
117 | total_open_fd++; | |
118 | if (total_open_fd > open_fd_hw) { | |
bccacf6c | 119 | v9fs_reclaim_fd(pdu); |
7a462745 AK |
120 | } |
121 | } | |
f6b7f0ab AK |
122 | return err; |
123 | } | |
e4de4232 | 124 | |
5bdade66 GK |
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) | |
e4de4232 VJ |
128 | { |
129 | int err; | |
130 | FsCred cred; | |
2289be19 | 131 | V9fsPath path; |
bccacf6c | 132 | V9fsState *s = pdu->s; |
2289be19 | 133 | |
bccacf6c AK |
134 | if (v9fs_request_cancelled(pdu)) { |
135 | return -EINTR; | |
136 | } | |
e4de4232 VJ |
137 | cred_init(&cred); |
138 | cred.fc_mode = mode & 07777; | |
139 | cred.fc_uid = fidp->uid; | |
140 | cred.fc_gid = gid; | |
02cb7f3a AK |
141 | /* |
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. | |
145 | */ | |
532decb7 | 146 | v9fs_path_read_lock(s); |
e4de4232 VJ |
147 | v9fs_co_run_in_worker( |
148 | { | |
cc720ddb AK |
149 | err = s->ops->open2(&s->ctx, &fidp->path, |
150 | name->data, flags, &cred, &fidp->fs); | |
151 | if (err < 0) { | |
e4de4232 | 152 | err = -errno; |
02cb7f3a | 153 | } else { |
2289be19 AK |
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; | |
cc720ddb | 160 | s->ops->close(&s->ctx, &fidp->fs); |
2289be19 AK |
161 | } else { |
162 | v9fs_path_copy(&fidp->path, &path); | |
163 | } | |
02cb7f3a | 164 | } else { |
cc720ddb | 165 | s->ops->close(&s->ctx, &fidp->fs); |
02cb7f3a | 166 | } |
2289be19 | 167 | v9fs_path_free(&path); |
e4de4232 VJ |
168 | } |
169 | }); | |
532decb7 | 170 | v9fs_path_unlock(s); |
7a462745 AK |
171 | if (!err) { |
172 | total_open_fd++; | |
173 | if (total_open_fd > open_fd_hw) { | |
bccacf6c | 174 | v9fs_reclaim_fd(pdu); |
7a462745 AK |
175 | } |
176 | } | |
e4de4232 VJ |
177 | return err; |
178 | } | |
bed4352c | 179 | |
5bdade66 | 180 | int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs) |
bed4352c | 181 | { |
bed4352c | 182 | int err; |
bccacf6c | 183 | V9fsState *s = pdu->s; |
bed4352c | 184 | |
bccacf6c AK |
185 | if (v9fs_request_cancelled(pdu)) { |
186 | return -EINTR; | |
187 | } | |
bed4352c AK |
188 | v9fs_co_run_in_worker( |
189 | { | |
cc720ddb | 190 | err = s->ops->close(&s->ctx, fs); |
bed4352c AK |
191 | if (err < 0) { |
192 | err = -errno; | |
193 | } | |
194 | }); | |
7a462745 AK |
195 | if (!err) { |
196 | total_open_fd--; | |
197 | } | |
bed4352c AK |
198 | return err; |
199 | } | |
4743d1f5 | 200 | |
5bdade66 | 201 | int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) |
4743d1f5 | 202 | { |
cc720ddb | 203 | int err; |
bccacf6c | 204 | V9fsState *s = pdu->s; |
4743d1f5 | 205 | |
bccacf6c AK |
206 | if (v9fs_request_cancelled(pdu)) { |
207 | return -EINTR; | |
208 | } | |
4743d1f5 AK |
209 | v9fs_co_run_in_worker( |
210 | { | |
8b888272 | 211 | err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync); |
4743d1f5 AK |
212 | if (err < 0) { |
213 | err = -errno; | |
214 | } | |
215 | }); | |
216 | return err; | |
217 | } | |
c6c069b0 | 218 | |
5bdade66 GK |
219 | int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, |
220 | V9fsFidState *newdirfid, V9fsString *name) | |
c6c069b0 VJ |
221 | { |
222 | int err; | |
bccacf6c | 223 | V9fsState *s = pdu->s; |
c6c069b0 | 224 | |
bccacf6c AK |
225 | if (v9fs_request_cancelled(pdu)) { |
226 | return -EINTR; | |
227 | } | |
532decb7 | 228 | v9fs_path_read_lock(s); |
c6c069b0 VJ |
229 | v9fs_co_run_in_worker( |
230 | { | |
2289be19 AK |
231 | err = s->ops->link(&s->ctx, &oldfid->path, |
232 | &newdirfid->path, name->data); | |
c6c069b0 VJ |
233 | if (err < 0) { |
234 | err = -errno; | |
235 | } | |
236 | }); | |
532decb7 | 237 | v9fs_path_unlock(s); |
c6c069b0 VJ |
238 | return err; |
239 | } | |
f6b3c976 | 240 | |
5bdade66 GK |
241 | int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, |
242 | struct iovec *iov, int iovcnt, int64_t offset) | |
f6b3c976 | 243 | { |
cc720ddb | 244 | int err; |
bccacf6c | 245 | V9fsState *s = pdu->s; |
f6b3c976 | 246 | |
bccacf6c AK |
247 | if (v9fs_request_cancelled(pdu)) { |
248 | return -EINTR; | |
249 | } | |
f6b3c976 AK |
250 | v9fs_co_run_in_worker( |
251 | { | |
cc720ddb | 252 | err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset); |
f6b3c976 AK |
253 | if (err < 0) { |
254 | err = -errno; | |
255 | } | |
256 | }); | |
257 | return err; | |
258 | } | |
7eafdcc9 | 259 | |
5bdade66 GK |
260 | int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, |
261 | struct iovec *iov, int iovcnt, int64_t offset) | |
7eafdcc9 | 262 | { |
cc720ddb | 263 | int err; |
bccacf6c | 264 | V9fsState *s = pdu->s; |
7eafdcc9 | 265 | |
bccacf6c AK |
266 | if (v9fs_request_cancelled(pdu)) { |
267 | return -EINTR; | |
268 | } | |
7eafdcc9 AK |
269 | v9fs_co_run_in_worker( |
270 | { | |
cc720ddb | 271 | err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset); |
7eafdcc9 AK |
272 | if (err < 0) { |
273 | err = -errno; | |
274 | } | |
275 | }); | |
276 | return err; | |
277 | } |