xref: /openbmc/qemu/hw/9pfs/cofile.c (revision 00ea69f5)
1172198d4SAneesh Kumar K.V /*
2af8b38b0SGreg Kurz  * 9p backend
3172198d4SAneesh Kumar K.V  *
4172198d4SAneesh Kumar K.V  * Copyright IBM, Corp. 2011
5172198d4SAneesh Kumar K.V  *
6172198d4SAneesh Kumar K.V  * Authors:
7172198d4SAneesh Kumar K.V  *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8172198d4SAneesh Kumar K.V  *
9172198d4SAneesh Kumar K.V  * This work is licensed under the terms of the GNU GPL, version 2.  See
10172198d4SAneesh Kumar K.V  * the COPYING file in the top-level directory.
11172198d4SAneesh Kumar K.V  *
12172198d4SAneesh Kumar K.V  */
13172198d4SAneesh Kumar K.V 
146f569084SChristian Schoenebeck /*
156f569084SChristian Schoenebeck  * Not so fast! You might want to read the 9p developer docs first:
166f569084SChristian Schoenebeck  * https://wiki.qemu.org/Documentation/9p
176f569084SChristian Schoenebeck  */
186f569084SChristian Schoenebeck 
19fbc04127SPeter Maydell #include "qemu/osdep.h"
20172198d4SAneesh Kumar K.V #include "fsdev/qemu-fsdev.h"
211de7afc9SPaolo Bonzini #include "qemu/thread.h"
22db725815SMarkus Armbruster #include "qemu/main-loop.h"
23fe52840cSWei Liu #include "coth.h"
24172198d4SAneesh Kumar K.V 
v9fs_co_st_gen(V9fsPDU * pdu,V9fsPath * path,mode_t st_mode,V9fsStatDotl * v9stat)255bdade66SGreg Kurz int coroutine_fn v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
26e06a765eSHarsh Prateek Bora                                 V9fsStatDotl *v9stat)
27e06a765eSHarsh Prateek Bora {
28e06a765eSHarsh Prateek Bora     int err = 0;
29e06a765eSHarsh Prateek Bora     V9fsState *s = pdu->s;
30e06a765eSHarsh Prateek Bora 
31e06a765eSHarsh Prateek Bora     if (v9fs_request_cancelled(pdu)) {
32e06a765eSHarsh Prateek Bora         return -EINTR;
33e06a765eSHarsh Prateek Bora     }
34e06a765eSHarsh Prateek Bora     if (s->ctx.exops.get_st_gen) {
35e06a765eSHarsh Prateek Bora         v9fs_path_read_lock(s);
36e06a765eSHarsh Prateek Bora         v9fs_co_run_in_worker(
37e06a765eSHarsh Prateek Bora             {
38e06a765eSHarsh Prateek Bora                 err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
39e06a765eSHarsh Prateek Bora                                               &v9stat->st_gen);
40e06a765eSHarsh Prateek Bora                 if (err < 0) {
41e06a765eSHarsh Prateek Bora                     err = -errno;
42e06a765eSHarsh Prateek Bora                 }
43e06a765eSHarsh Prateek Bora             });
44e06a765eSHarsh Prateek Bora         v9fs_path_unlock(s);
45e06a765eSHarsh Prateek Bora     }
46e06a765eSHarsh Prateek Bora     return err;
47e06a765eSHarsh Prateek Bora }
48e06a765eSHarsh Prateek Bora 
v9fs_co_lstat(V9fsPDU * pdu,V9fsPath * path,struct stat * stbuf)495bdade66SGreg Kurz int coroutine_fn v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
50172198d4SAneesh Kumar K.V {
51172198d4SAneesh Kumar K.V     int err;
52bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
53172198d4SAneesh Kumar K.V 
54bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
55bccacf6cSAneesh Kumar K.V         return -EINTR;
56bccacf6cSAneesh Kumar K.V     }
57532decb7SAneesh Kumar K.V     v9fs_path_read_lock(s);
58172198d4SAneesh Kumar K.V     v9fs_co_run_in_worker(
59172198d4SAneesh Kumar K.V         {
602289be19SAneesh Kumar K.V             err = s->ops->lstat(&s->ctx, path, stbuf);
61172198d4SAneesh Kumar K.V             if (err < 0) {
62172198d4SAneesh Kumar K.V                 err = -errno;
63172198d4SAneesh Kumar K.V             }
64172198d4SAneesh Kumar K.V         });
65532decb7SAneesh Kumar K.V     v9fs_path_unlock(s);
66172198d4SAneesh Kumar K.V     return err;
67172198d4SAneesh Kumar K.V }
6803feb1e1SAneesh Kumar K.V 
v9fs_co_fstat(V9fsPDU * pdu,V9fsFidState * fidp,struct stat * stbuf)695bdade66SGreg Kurz int coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp,
705bdade66SGreg Kurz                                struct stat *stbuf)
7103feb1e1SAneesh Kumar K.V {
7203feb1e1SAneesh Kumar K.V     int err;
73bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
7403feb1e1SAneesh Kumar K.V 
75bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
76bccacf6cSAneesh Kumar K.V         return -EINTR;
77bccacf6cSAneesh Kumar K.V     }
7803feb1e1SAneesh Kumar K.V     v9fs_co_run_in_worker(
7903feb1e1SAneesh Kumar K.V         {
808b888272SAneesh Kumar K.V             err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
8103feb1e1SAneesh Kumar K.V             if (err < 0) {
8203feb1e1SAneesh Kumar K.V                 err = -errno;
8303feb1e1SAneesh Kumar K.V             }
8403feb1e1SAneesh Kumar K.V         });
852c30dd74SAneesh Kumar K.V     /*
862c30dd74SAneesh Kumar K.V      * Some FS driver (local:mapped-file) can't support fetching attributes
872c30dd74SAneesh Kumar K.V      * using file descriptor. Use Path name in that case.
882c30dd74SAneesh Kumar K.V      */
892c30dd74SAneesh Kumar K.V     if (err == -EOPNOTSUPP) {
902c30dd74SAneesh Kumar K.V         err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
912c30dd74SAneesh Kumar K.V         if (err == -ENOENT) {
922c30dd74SAneesh Kumar K.V             /*
932c30dd74SAneesh Kumar K.V              * fstat on an unlinked file. Work with partial results
942c30dd74SAneesh Kumar K.V              * returned from s->ops->fstat
952c30dd74SAneesh Kumar K.V              */
962c30dd74SAneesh Kumar K.V             err = 0;
972c30dd74SAneesh Kumar K.V         }
982c30dd74SAneesh Kumar K.V     }
9903feb1e1SAneesh Kumar K.V     return err;
10003feb1e1SAneesh Kumar K.V }
101f6b7f0abSAneesh Kumar K.V 
v9fs_co_open(V9fsPDU * pdu,V9fsFidState * fidp,int flags)1025bdade66SGreg Kurz int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
103f6b7f0abSAneesh Kumar K.V {
104f6b7f0abSAneesh Kumar K.V     int err;
105bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
106f6b7f0abSAneesh Kumar K.V 
107bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
108bccacf6cSAneesh Kumar K.V         return -EINTR;
109bccacf6cSAneesh Kumar K.V     }
110532decb7SAneesh Kumar K.V     v9fs_path_read_lock(s);
111f6b7f0abSAneesh Kumar K.V     v9fs_co_run_in_worker(
112f6b7f0abSAneesh Kumar K.V         {
113cc720ddbSAneesh Kumar K.V             err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
114cc720ddbSAneesh Kumar K.V             if (err == -1) {
115f6b7f0abSAneesh Kumar K.V                 err = -errno;
116f6b7f0abSAneesh Kumar K.V             } else {
117f6b7f0abSAneesh Kumar K.V                 err = 0;
118f6b7f0abSAneesh Kumar K.V             }
119f6b7f0abSAneesh Kumar K.V         });
120532decb7SAneesh Kumar K.V     v9fs_path_unlock(s);
1217a462745SAneesh Kumar K.V     if (!err) {
1227a462745SAneesh Kumar K.V         total_open_fd++;
1237a462745SAneesh Kumar K.V         if (total_open_fd > open_fd_hw) {
124bccacf6cSAneesh Kumar K.V             v9fs_reclaim_fd(pdu);
1257a462745SAneesh Kumar K.V         }
1267a462745SAneesh Kumar K.V     }
127f6b7f0abSAneesh Kumar K.V     return err;
128f6b7f0abSAneesh Kumar K.V }
129e4de4232SVenkateswararao Jujjuri 
v9fs_co_open2(V9fsPDU * pdu,V9fsFidState * fidp,V9fsString * name,gid_t gid,int flags,int mode,struct stat * stbuf)1305bdade66SGreg Kurz int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
1315bdade66SGreg Kurz                                V9fsString *name, gid_t gid, int flags, int mode,
1325bdade66SGreg Kurz                                struct stat *stbuf)
133e4de4232SVenkateswararao Jujjuri {
134e4de4232SVenkateswararao Jujjuri     int err;
135e4de4232SVenkateswararao Jujjuri     FsCred cred;
1362289be19SAneesh Kumar K.V     V9fsPath path;
137bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
1382289be19SAneesh Kumar K.V 
139bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
140bccacf6cSAneesh Kumar K.V         return -EINTR;
141bccacf6cSAneesh Kumar K.V     }
142e4de4232SVenkateswararao Jujjuri     cred_init(&cred);
143e4de4232SVenkateswararao Jujjuri     cred.fc_mode = mode & 07777;
144e4de4232SVenkateswararao Jujjuri     cred.fc_uid = fidp->uid;
145e4de4232SVenkateswararao Jujjuri     cred.fc_gid = gid;
14602cb7f3aSAneesh Kumar K.V     /*
14702cb7f3aSAneesh Kumar K.V      * Hold the directory fid lock so that directory path name
1485b76ef50SGreg Kurz      * don't change. Take the write lock to be sure this fid
1495b76ef50SGreg Kurz      * cannot be used by another operation.
15002cb7f3aSAneesh Kumar K.V      */
1515b76ef50SGreg Kurz     v9fs_path_write_lock(s);
152e4de4232SVenkateswararao Jujjuri     v9fs_co_run_in_worker(
153e4de4232SVenkateswararao Jujjuri         {
154cc720ddbSAneesh Kumar K.V             err = s->ops->open2(&s->ctx, &fidp->path,
155cc720ddbSAneesh Kumar K.V                                 name->data, flags, &cred, &fidp->fs);
156cc720ddbSAneesh Kumar K.V             if (err < 0) {
157e4de4232SVenkateswararao Jujjuri                 err = -errno;
15802cb7f3aSAneesh Kumar K.V             } else {
1592289be19SAneesh Kumar K.V                 v9fs_path_init(&path);
1602289be19SAneesh Kumar K.V                 err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
1612289be19SAneesh Kumar K.V                 if (!err) {
1622289be19SAneesh Kumar K.V                     err = s->ops->lstat(&s->ctx, &path, stbuf);
16302cb7f3aSAneesh Kumar K.V                     if (err < 0) {
16402cb7f3aSAneesh Kumar K.V                         err = -errno;
165cc720ddbSAneesh Kumar K.V                         s->ops->close(&s->ctx, &fidp->fs);
16602cb7f3aSAneesh Kumar K.V                     } else {
1672289be19SAneesh Kumar K.V                         v9fs_path_copy(&fidp->path, &path);
16802cb7f3aSAneesh Kumar K.V                     }
1692289be19SAneesh Kumar K.V                 } else {
170cc720ddbSAneesh Kumar K.V                     s->ops->close(&s->ctx, &fidp->fs);
1712289be19SAneesh Kumar K.V                 }
1722289be19SAneesh Kumar K.V                 v9fs_path_free(&path);
173e4de4232SVenkateswararao Jujjuri             }
174e4de4232SVenkateswararao Jujjuri         });
175532decb7SAneesh Kumar K.V     v9fs_path_unlock(s);
1767a462745SAneesh Kumar K.V     if (!err) {
1777a462745SAneesh Kumar K.V         total_open_fd++;
1787a462745SAneesh Kumar K.V         if (total_open_fd > open_fd_hw) {
179bccacf6cSAneesh Kumar K.V             v9fs_reclaim_fd(pdu);
1807a462745SAneesh Kumar K.V         }
1817a462745SAneesh Kumar K.V     }
182e4de4232SVenkateswararao Jujjuri     return err;
183e4de4232SVenkateswararao Jujjuri }
184bed4352cSAneesh Kumar K.V 
v9fs_co_close(V9fsPDU * pdu,V9fsFidOpenState * fs)1855bdade66SGreg Kurz int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
186bed4352cSAneesh Kumar K.V {
187bed4352cSAneesh Kumar K.V     int err;
188bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
189bed4352cSAneesh Kumar K.V 
190bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
191bccacf6cSAneesh Kumar K.V         return -EINTR;
192bccacf6cSAneesh Kumar K.V     }
193bed4352cSAneesh Kumar K.V     v9fs_co_run_in_worker(
194bed4352cSAneesh Kumar K.V         {
195cc720ddbSAneesh Kumar K.V             err = s->ops->close(&s->ctx, fs);
196bed4352cSAneesh Kumar K.V             if (err < 0) {
197bed4352cSAneesh Kumar K.V                 err = -errno;
198bed4352cSAneesh Kumar K.V             }
199bed4352cSAneesh Kumar K.V         });
2007a462745SAneesh Kumar K.V     if (!err) {
2017a462745SAneesh Kumar K.V         total_open_fd--;
2027a462745SAneesh Kumar K.V     }
203bed4352cSAneesh Kumar K.V     return err;
204bed4352cSAneesh Kumar K.V }
2054743d1f5SAneesh Kumar K.V 
v9fs_co_fsync(V9fsPDU * pdu,V9fsFidState * fidp,int datasync)2065bdade66SGreg Kurz int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
2074743d1f5SAneesh Kumar K.V {
208cc720ddbSAneesh Kumar K.V     int err;
209bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
2104743d1f5SAneesh Kumar K.V 
211bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
212bccacf6cSAneesh Kumar K.V         return -EINTR;
213bccacf6cSAneesh Kumar K.V     }
2144743d1f5SAneesh Kumar K.V     v9fs_co_run_in_worker(
2154743d1f5SAneesh Kumar K.V         {
2168b888272SAneesh Kumar K.V             err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
2174743d1f5SAneesh Kumar K.V             if (err < 0) {
2184743d1f5SAneesh Kumar K.V                 err = -errno;
2194743d1f5SAneesh Kumar K.V             }
2204743d1f5SAneesh Kumar K.V         });
2214743d1f5SAneesh Kumar K.V     return err;
2224743d1f5SAneesh Kumar K.V }
223c6c069b0SVenkateswararao Jujjuri 
v9fs_co_link(V9fsPDU * pdu,V9fsFidState * oldfid,V9fsFidState * newdirfid,V9fsString * name)2245bdade66SGreg Kurz int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
2252289be19SAneesh Kumar K.V                               V9fsFidState *newdirfid, V9fsString *name)
226c6c069b0SVenkateswararao Jujjuri {
227c6c069b0SVenkateswararao Jujjuri     int err;
228bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
229c6c069b0SVenkateswararao Jujjuri 
230bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
231bccacf6cSAneesh Kumar K.V         return -EINTR;
232bccacf6cSAneesh Kumar K.V     }
233532decb7SAneesh Kumar K.V     v9fs_path_read_lock(s);
234c6c069b0SVenkateswararao Jujjuri     v9fs_co_run_in_worker(
235c6c069b0SVenkateswararao Jujjuri         {
2362289be19SAneesh Kumar K.V             err = s->ops->link(&s->ctx, &oldfid->path,
2372289be19SAneesh Kumar K.V                                &newdirfid->path, name->data);
238c6c069b0SVenkateswararao Jujjuri             if (err < 0) {
239c6c069b0SVenkateswararao Jujjuri                 err = -errno;
240c6c069b0SVenkateswararao Jujjuri             }
241c6c069b0SVenkateswararao Jujjuri         });
242532decb7SAneesh Kumar K.V     v9fs_path_unlock(s);
243c6c069b0SVenkateswararao Jujjuri     return err;
244c6c069b0SVenkateswararao Jujjuri }
245f6b3c976SAneesh Kumar K.V 
v9fs_co_pwritev(V9fsPDU * pdu,V9fsFidState * fidp,struct iovec * iov,int iovcnt,int64_t offset)2465bdade66SGreg Kurz int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
247f6b3c976SAneesh Kumar K.V                                  struct iovec *iov, int iovcnt, int64_t offset)
248f6b3c976SAneesh Kumar K.V {
249cc720ddbSAneesh Kumar K.V     int err;
250bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
251f6b3c976SAneesh Kumar K.V 
252bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
253bccacf6cSAneesh Kumar K.V         return -EINTR;
254bccacf6cSAneesh Kumar K.V     }
255*00ea69f5Szhenwei pi     fsdev_co_throttle_request(s->ctx.fst, THROTTLE_WRITE, iov, iovcnt);
256f6b3c976SAneesh Kumar K.V     v9fs_co_run_in_worker(
257f6b3c976SAneesh Kumar K.V         {
258cc720ddbSAneesh Kumar K.V             err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
259f6b3c976SAneesh Kumar K.V             if (err < 0) {
260f6b3c976SAneesh Kumar K.V                 err = -errno;
261f6b3c976SAneesh Kumar K.V             }
262f6b3c976SAneesh Kumar K.V         });
263f6b3c976SAneesh Kumar K.V     return err;
264f6b3c976SAneesh Kumar K.V }
2657eafdcc9SAneesh Kumar K.V 
v9fs_co_preadv(V9fsPDU * pdu,V9fsFidState * fidp,struct iovec * iov,int iovcnt,int64_t offset)2665bdade66SGreg Kurz int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
2677eafdcc9SAneesh Kumar K.V                                 struct iovec *iov, int iovcnt, int64_t offset)
2687eafdcc9SAneesh Kumar K.V {
269cc720ddbSAneesh Kumar K.V     int err;
270bccacf6cSAneesh Kumar K.V     V9fsState *s = pdu->s;
2717eafdcc9SAneesh Kumar K.V 
272bccacf6cSAneesh Kumar K.V     if (v9fs_request_cancelled(pdu)) {
273bccacf6cSAneesh Kumar K.V         return -EINTR;
274bccacf6cSAneesh Kumar K.V     }
275*00ea69f5Szhenwei pi     fsdev_co_throttle_request(s->ctx.fst, THROTTLE_READ, iov, iovcnt);
2767eafdcc9SAneesh Kumar K.V     v9fs_co_run_in_worker(
2777eafdcc9SAneesh Kumar K.V         {
278cc720ddbSAneesh Kumar K.V             err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
2797eafdcc9SAneesh Kumar K.V             if (err < 0) {
2807eafdcc9SAneesh Kumar K.V                 err = -errno;
2817eafdcc9SAneesh Kumar K.V             }
2827eafdcc9SAneesh Kumar K.V         });
2837eafdcc9SAneesh Kumar K.V     return err;
2847eafdcc9SAneesh Kumar K.V }
285