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