xref: /openbmc/qemu/hw/9pfs/codir.c (revision a719a27c)
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"
16 #include "qemu/thread.h"
17 #include "block/coroutine.h"
18 #include "virtio-9p-coth.h"
19 
20 int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
21                       struct dirent **result)
22 {
23     int err;
24     V9fsState *s = pdu->s;
25 
26     if (v9fs_request_cancelled(pdu)) {
27         return -EINTR;
28     }
29     v9fs_co_run_in_worker(
30         {
31             errno = 0;
32             err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result);
33             if (!*result && errno) {
34                 err = -errno;
35             } else {
36                 err = 0;
37             }
38         });
39     return err;
40 }
41 
42 off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp)
43 {
44     off_t err;
45     V9fsState *s = pdu->s;
46 
47     if (v9fs_request_cancelled(pdu)) {
48         return -EINTR;
49     }
50     v9fs_co_run_in_worker(
51         {
52             err = s->ops->telldir(&s->ctx, &fidp->fs);
53             if (err < 0) {
54                 err = -errno;
55             }
56         });
57     return err;
58 }
59 
60 void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset)
61 {
62     V9fsState *s = pdu->s;
63     if (v9fs_request_cancelled(pdu)) {
64         return;
65     }
66     v9fs_co_run_in_worker(
67         {
68             s->ops->seekdir(&s->ctx, &fidp->fs, offset);
69         });
70 }
71 
72 void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp)
73 {
74     V9fsState *s = pdu->s;
75     if (v9fs_request_cancelled(pdu)) {
76         return;
77     }
78     v9fs_co_run_in_worker(
79         {
80             s->ops->rewinddir(&s->ctx, &fidp->fs);
81         });
82 }
83 
84 int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
85                   mode_t mode, uid_t uid, gid_t gid, struct stat *stbuf)
86 {
87     int err;
88     FsCred cred;
89     V9fsPath path;
90     V9fsState *s = pdu->s;
91 
92     if (v9fs_request_cancelled(pdu)) {
93         return -EINTR;
94     }
95     cred_init(&cred);
96     cred.fc_mode = mode;
97     cred.fc_uid = uid;
98     cred.fc_gid = gid;
99     v9fs_path_read_lock(s);
100     v9fs_co_run_in_worker(
101         {
102             err = s->ops->mkdir(&s->ctx, &fidp->path, name->data,  &cred);
103             if (err < 0) {
104                 err = -errno;
105             } else {
106                 v9fs_path_init(&path);
107                 err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
108                 if (!err) {
109                     err = s->ops->lstat(&s->ctx, &path, stbuf);
110                     if (err < 0) {
111                         err = -errno;
112                     }
113                 }
114                 v9fs_path_free(&path);
115             }
116         });
117     v9fs_path_unlock(s);
118     return err;
119 }
120 
121 int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp)
122 {
123     int err;
124     V9fsState *s = pdu->s;
125 
126     if (v9fs_request_cancelled(pdu)) {
127         return -EINTR;
128     }
129     v9fs_path_read_lock(s);
130     v9fs_co_run_in_worker(
131         {
132             err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs);
133             if (err < 0) {
134                 err = -errno;
135             } else {
136                 err = 0;
137             }
138         });
139     v9fs_path_unlock(s);
140     if (!err) {
141         total_open_fd++;
142         if (total_open_fd > open_fd_hw) {
143             v9fs_reclaim_fd(pdu);
144         }
145     }
146     return err;
147 }
148 
149 int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs)
150 {
151     int err;
152     V9fsState *s = pdu->s;
153 
154     if (v9fs_request_cancelled(pdu)) {
155         return -EINTR;
156     }
157     v9fs_co_run_in_worker(
158         {
159             err = s->ops->closedir(&s->ctx, fs);
160             if (err < 0) {
161                 err = -errno;
162             }
163         });
164     if (!err) {
165         total_open_fd--;
166     }
167     return err;
168 }
169