|
|
1.1 root 1:
2: /*
3: * Virtio 9p backend
4: *
5: * Copyright IBM, Corp. 2011
6: *
7: * Authors:
8: * Aneesh Kumar K.V <[email protected]>
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 "qemu-coroutine.h"
18: #include "virtio-9p-coth.h"
19:
20: int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
21: {
22: int err;
23: ssize_t len;
24: V9fsState *s = pdu->s;
25:
26: if (v9fs_request_cancelled(pdu)) {
27: return -EINTR;
28: }
29: buf->data = g_malloc(PATH_MAX);
30: v9fs_path_read_lock(s);
31: v9fs_co_run_in_worker(
32: {
33: len = s->ops->readlink(&s->ctx, path,
34: buf->data, PATH_MAX - 1);
35: if (len > -1) {
36: buf->size = len;
37: buf->data[len] = 0;
38: err = 0;
39: } else {
40: err = -errno;
41: }
42: });
43: v9fs_path_unlock(s);
44: if (err) {
45: g_free(buf->data);
46: buf->data = NULL;
47: buf->size = 0;
48: }
49: return err;
50: }
51:
52: int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, struct statfs *stbuf)
53: {
54: int err;
55: V9fsState *s = pdu->s;
56:
57: if (v9fs_request_cancelled(pdu)) {
58: return -EINTR;
59: }
60: v9fs_path_read_lock(s);
61: v9fs_co_run_in_worker(
62: {
63: err = s->ops->statfs(&s->ctx, path, stbuf);
64: if (err < 0) {
65: err = -errno;
66: }
67: });
68: v9fs_path_unlock(s);
69: return err;
70: }
71:
72: int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode)
73: {
74: int err;
75: FsCred cred;
76: V9fsState *s = pdu->s;
77:
78: if (v9fs_request_cancelled(pdu)) {
79: return -EINTR;
80: }
81: cred_init(&cred);
82: cred.fc_mode = mode;
83: v9fs_path_read_lock(s);
84: v9fs_co_run_in_worker(
85: {
86: err = s->ops->chmod(&s->ctx, path, &cred);
87: if (err < 0) {
88: err = -errno;
89: }
90: });
91: v9fs_path_unlock(s);
92: return err;
93: }
94:
95: int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
96: struct timespec times[2])
97: {
98: int err;
99: V9fsState *s = pdu->s;
100:
101: if (v9fs_request_cancelled(pdu)) {
102: return -EINTR;
103: }
104: v9fs_path_read_lock(s);
105: v9fs_co_run_in_worker(
106: {
107: err = s->ops->utimensat(&s->ctx, path, times);
108: if (err < 0) {
109: err = -errno;
110: }
111: });
112: v9fs_path_unlock(s);
113: return err;
114: }
115:
116: int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid)
117: {
118: int err;
119: FsCred cred;
120: V9fsState *s = pdu->s;
121:
122: if (v9fs_request_cancelled(pdu)) {
123: return -EINTR;
124: }
125: cred_init(&cred);
126: cred.fc_uid = uid;
127: cred.fc_gid = gid;
128: v9fs_path_read_lock(s);
129: v9fs_co_run_in_worker(
130: {
131: err = s->ops->chown(&s->ctx, path, &cred);
132: if (err < 0) {
133: err = -errno;
134: }
135: });
136: v9fs_path_unlock(s);
137: return err;
138: }
139:
140: int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size)
141: {
142: int err;
143: V9fsState *s = pdu->s;
144:
145: if (v9fs_request_cancelled(pdu)) {
146: return -EINTR;
147: }
148: v9fs_path_read_lock(s);
149: v9fs_co_run_in_worker(
150: {
151: err = s->ops->truncate(&s->ctx, path, size);
152: if (err < 0) {
153: err = -errno;
154: }
155: });
156: v9fs_path_unlock(s);
157: return err;
158: }
159:
160: int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid,
161: gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
162: {
163: int err;
164: V9fsPath path;
165: FsCred cred;
166: V9fsState *s = pdu->s;
167:
168: if (v9fs_request_cancelled(pdu)) {
169: return -EINTR;
170: }
171: cred_init(&cred);
172: cred.fc_uid = uid;
173: cred.fc_gid = gid;
174: cred.fc_mode = mode;
175: cred.fc_rdev = dev;
176: v9fs_path_read_lock(s);
177: v9fs_co_run_in_worker(
178: {
179: err = s->ops->mknod(&s->ctx, &fidp->path, name->data, &cred);
180: if (err < 0) {
181: err = -errno;
182: } else {
183: v9fs_path_init(&path);
184: err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
185: if (!err) {
186: err = s->ops->lstat(&s->ctx, &path, stbuf);
187: if (err < 0) {
188: err = -errno;
189: }
190: }
191: v9fs_path_free(&path);
192: }
193: });
194: v9fs_path_unlock(s);
195: return err;
196: }
197:
198: /* Only works with path name based fid */
199: int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path)
200: {
201: int err;
202: V9fsState *s = pdu->s;
203:
204: if (v9fs_request_cancelled(pdu)) {
205: return -EINTR;
206: }
207: v9fs_path_read_lock(s);
208: v9fs_co_run_in_worker(
209: {
210: err = s->ops->remove(&s->ctx, path->data);
211: if (err < 0) {
212: err = -errno;
213: }
214: });
215: v9fs_path_unlock(s);
216: return err;
217: }
218:
219: int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9fsString *name, int flags)
220: {
221: int err;
222: V9fsState *s = pdu->s;
223:
224: if (v9fs_request_cancelled(pdu)) {
225: return -EINTR;
226: }
227: v9fs_path_read_lock(s);
228: v9fs_co_run_in_worker(
229: {
230: err = s->ops->unlinkat(&s->ctx, path, name->data, flags);
231: if (err < 0) {
232: err = -errno;
233: }
234: });
235: v9fs_path_unlock(s);
236: return err;
237: }
238:
239: /* Only work with path name based fid */
240: int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V9fsPath *newpath)
241: {
242: int err;
243: V9fsState *s = pdu->s;
244:
245: if (v9fs_request_cancelled(pdu)) {
246: return -EINTR;
247: }
248: v9fs_co_run_in_worker(
249: {
250: err = s->ops->rename(&s->ctx, oldpath->data, newpath->data);
251: if (err < 0) {
252: err = -errno;
253: }
254: });
255: return err;
256: }
257:
258: int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpath, V9fsString *oldname,
259: V9fsPath *newdirpath, V9fsString *newname)
260: {
261: int err;
262: V9fsState *s = pdu->s;
263:
264: if (v9fs_request_cancelled(pdu)) {
265: return -EINTR;
266: }
267: v9fs_co_run_in_worker(
268: {
269: err = s->ops->renameat(&s->ctx, olddirpath, oldname->data,
270: newdirpath, newname->data);
271: if (err < 0) {
272: err = -errno;
273: }
274: });
275: return err;
276: }
277:
278: int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState *dfidp, V9fsString *name,
279: const char *oldpath, gid_t gid, struct stat *stbuf)
280: {
281: int err;
282: FsCred cred;
283: V9fsPath path;
284: V9fsState *s = pdu->s;
285:
286: if (v9fs_request_cancelled(pdu)) {
287: return -EINTR;
288: }
289: cred_init(&cred);
290: cred.fc_uid = dfidp->uid;
291: cred.fc_gid = gid;
292: cred.fc_mode = 0777;
293: v9fs_path_read_lock(s);
294: v9fs_co_run_in_worker(
295: {
296: err = s->ops->symlink(&s->ctx, oldpath, &dfidp->path,
297: name->data, &cred);
298: if (err < 0) {
299: err = -errno;
300: } else {
301: v9fs_path_init(&path);
302: err = v9fs_name_to_path(s, &dfidp->path, name->data, &path);
303: if (!err) {
304: err = s->ops->lstat(&s->ctx, &path, stbuf);
305: if (err < 0) {
306: err = -errno;
307: }
308: }
309: v9fs_path_free(&path);
310: }
311: });
312: v9fs_path_unlock(s);
313: return err;
314: }
315:
316: /*
317: * For path name based fid we don't block. So we can
318: * directly call the fs driver ops.
319: */
320: int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath,
321: const char *name, V9fsPath *path)
322: {
323: int err;
324: V9fsState *s = pdu->s;
325:
326: if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
327: err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
328: if (err < 0) {
329: err = -errno;
330: }
331: } else {
332: if (v9fs_request_cancelled(pdu)) {
333: return -EINTR;
334: }
335: v9fs_co_run_in_worker(
336: {
337: err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
338: if (err < 0) {
339: err = -errno;
340: }
341: });
342: }
343: return err;
344: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.