]> git.proxmox.com Git - mirror_qemu.git/blame - hw/9pfs/cofile.c
spapr_pci: Fix interrupt leak in rtas_ibm_change_msi() error path
[mirror_qemu.git] / hw / 9pfs / cofile.c
CommitLineData
172198d4 1/*
af8b38b0 2 * 9p backend
172198d4
AK
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
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
20int 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 44int 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
64int 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 97int 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
125int 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
5b76ef50
GK
143 * don't change. Take the write lock to be sure this fid
144 * cannot be used by another operation.
02cb7f3a 145 */
5b76ef50 146 v9fs_path_write_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 180int 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 201int 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
219int 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
241int 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 }
b8bbdb88 250 fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
f6b3c976
AK
251 v9fs_co_run_in_worker(
252 {
cc720ddb 253 err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
f6b3c976
AK
254 if (err < 0) {
255 err = -errno;
256 }
257 });
258 return err;
259}
7eafdcc9 260
5bdade66
GK
261int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
262 struct iovec *iov, int iovcnt, int64_t offset)
7eafdcc9 263{
cc720ddb 264 int err;
bccacf6c 265 V9fsState *s = pdu->s;
7eafdcc9 266
bccacf6c
AK
267 if (v9fs_request_cancelled(pdu)) {
268 return -EINTR;
269 }
b8bbdb88 270 fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
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}