xref: /openbmc/qemu/hw/9pfs/9p.c (revision 24b94625)
1 /*
2  * Virtio 9p backend
3  *
4  * Copyright IBM, Corp. 2010
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.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 
14 #include "qemu/osdep.h"
15 #include <glib/gprintf.h>
16 #include "hw/virtio/virtio.h"
17 #include "qapi/error.h"
18 #include "qemu/error-report.h"
19 #include "qemu/iov.h"
20 #include "qemu/sockets.h"
21 #include "virtio-9p.h"
22 #include "fsdev/qemu-fsdev.h"
23 #include "9p-xattr.h"
24 #include "coth.h"
25 #include "trace.h"
26 #include "migration/migration.h"
27 
28 int open_fd_hw;
29 int total_open_fd;
30 static int open_fd_rc;
31 
32 enum {
33     Oread   = 0x00,
34     Owrite  = 0x01,
35     Ordwr   = 0x02,
36     Oexec   = 0x03,
37     Oexcl   = 0x04,
38     Otrunc  = 0x10,
39     Orexec  = 0x20,
40     Orclose = 0x40,
41     Oappend = 0x80,
42 };
43 
44 ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
45 {
46     ssize_t ret;
47     va_list ap;
48 
49     va_start(ap, fmt);
50     ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap);
51     va_end(ap);
52 
53     return ret;
54 }
55 
56 ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
57 {
58     ssize_t ret;
59     va_list ap;
60 
61     va_start(ap, fmt);
62     ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap);
63     va_end(ap);
64 
65     return ret;
66 }
67 
68 static void pdu_push_and_notify(V9fsPDU *pdu)
69 {
70     virtio_9p_push_and_notify(pdu);
71 }
72 
73 static int omode_to_uflags(int8_t mode)
74 {
75     int ret = 0;
76 
77     switch (mode & 3) {
78     case Oread:
79         ret = O_RDONLY;
80         break;
81     case Ordwr:
82         ret = O_RDWR;
83         break;
84     case Owrite:
85         ret = O_WRONLY;
86         break;
87     case Oexec:
88         ret = O_RDONLY;
89         break;
90     }
91 
92     if (mode & Otrunc) {
93         ret |= O_TRUNC;
94     }
95 
96     if (mode & Oappend) {
97         ret |= O_APPEND;
98     }
99 
100     if (mode & Oexcl) {
101         ret |= O_EXCL;
102     }
103 
104     return ret;
105 }
106 
107 struct dotl_openflag_map {
108     int dotl_flag;
109     int open_flag;
110 };
111 
112 static int dotl_to_open_flags(int flags)
113 {
114     int i;
115     /*
116      * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
117      * and P9_DOTL_NOACCESS
118      */
119     int oflags = flags & O_ACCMODE;
120 
121     struct dotl_openflag_map dotl_oflag_map[] = {
122         { P9_DOTL_CREATE, O_CREAT },
123         { P9_DOTL_EXCL, O_EXCL },
124         { P9_DOTL_NOCTTY , O_NOCTTY },
125         { P9_DOTL_TRUNC, O_TRUNC },
126         { P9_DOTL_APPEND, O_APPEND },
127         { P9_DOTL_NONBLOCK, O_NONBLOCK } ,
128         { P9_DOTL_DSYNC, O_DSYNC },
129         { P9_DOTL_FASYNC, FASYNC },
130         { P9_DOTL_DIRECT, O_DIRECT },
131         { P9_DOTL_LARGEFILE, O_LARGEFILE },
132         { P9_DOTL_DIRECTORY, O_DIRECTORY },
133         { P9_DOTL_NOFOLLOW, O_NOFOLLOW },
134         { P9_DOTL_NOATIME, O_NOATIME },
135         { P9_DOTL_SYNC, O_SYNC },
136     };
137 
138     for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
139         if (flags & dotl_oflag_map[i].dotl_flag) {
140             oflags |= dotl_oflag_map[i].open_flag;
141         }
142     }
143 
144     return oflags;
145 }
146 
147 void cred_init(FsCred *credp)
148 {
149     credp->fc_uid = -1;
150     credp->fc_gid = -1;
151     credp->fc_mode = -1;
152     credp->fc_rdev = -1;
153 }
154 
155 static int get_dotl_openflags(V9fsState *s, int oflags)
156 {
157     int flags;
158     /*
159      * Filter the client open flags
160      */
161     flags = dotl_to_open_flags(oflags);
162     flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
163     /*
164      * Ignore direct disk access hint until the server supports it.
165      */
166     flags &= ~O_DIRECT;
167     return flags;
168 }
169 
170 void v9fs_path_init(V9fsPath *path)
171 {
172     path->data = NULL;
173     path->size = 0;
174 }
175 
176 void v9fs_path_free(V9fsPath *path)
177 {
178     g_free(path->data);
179     path->data = NULL;
180     path->size = 0;
181 }
182 
183 
184 void GCC_FMT_ATTR(2, 3)
185 v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...)
186 {
187     va_list ap;
188 
189     v9fs_path_free(path);
190 
191     va_start(ap, fmt);
192     /* Bump the size for including terminating NULL */
193     path->size = g_vasprintf(&path->data, fmt, ap) + 1;
194     va_end(ap);
195 }
196 
197 void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs)
198 {
199     v9fs_path_free(lhs);
200     lhs->data = g_malloc(rhs->size);
201     memcpy(lhs->data, rhs->data, rhs->size);
202     lhs->size = rhs->size;
203 }
204 
205 int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
206                       const char *name, V9fsPath *path)
207 {
208     int err;
209     err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
210     if (err < 0) {
211         err = -errno;
212     }
213     return err;
214 }
215 
216 /*
217  * Return TRUE if s1 is an ancestor of s2.
218  *
219  * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d".
220  * As a special case, We treat s1 as ancestor of s2 if they are same!
221  */
222 static int v9fs_path_is_ancestor(V9fsPath *s1, V9fsPath *s2)
223 {
224     if (!strncmp(s1->data, s2->data, s1->size - 1)) {
225         if (s2->data[s1->size - 1] == '\0' || s2->data[s1->size - 1] == '/') {
226             return 1;
227         }
228     }
229     return 0;
230 }
231 
232 static size_t v9fs_string_size(V9fsString *str)
233 {
234     return str->size;
235 }
236 
237 /*
238  * returns 0 if fid got re-opened, 1 if not, < 0 on error */
239 static int coroutine_fn v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f)
240 {
241     int err = 1;
242     if (f->fid_type == P9_FID_FILE) {
243         if (f->fs.fd == -1) {
244             do {
245                 err = v9fs_co_open(pdu, f, f->open_flags);
246             } while (err == -EINTR && !pdu->cancelled);
247         }
248     } else if (f->fid_type == P9_FID_DIR) {
249         if (f->fs.dir.stream == NULL) {
250             do {
251                 err = v9fs_co_opendir(pdu, f);
252             } while (err == -EINTR && !pdu->cancelled);
253         }
254     }
255     return err;
256 }
257 
258 static V9fsFidState *coroutine_fn get_fid(V9fsPDU *pdu, int32_t fid)
259 {
260     int err;
261     V9fsFidState *f;
262     V9fsState *s = pdu->s;
263 
264     for (f = s->fid_list; f; f = f->next) {
265         BUG_ON(f->clunked);
266         if (f->fid == fid) {
267             /*
268              * Update the fid ref upfront so that
269              * we don't get reclaimed when we yield
270              * in open later.
271              */
272             f->ref++;
273             /*
274              * check whether we need to reopen the
275              * file. We might have closed the fd
276              * while trying to free up some file
277              * descriptors.
278              */
279             err = v9fs_reopen_fid(pdu, f);
280             if (err < 0) {
281                 f->ref--;
282                 return NULL;
283             }
284             /*
285              * Mark the fid as referenced so that the LRU
286              * reclaim won't close the file descriptor
287              */
288             f->flags |= FID_REFERENCED;
289             return f;
290         }
291     }
292     return NULL;
293 }
294 
295 static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
296 {
297     V9fsFidState *f;
298 
299     for (f = s->fid_list; f; f = f->next) {
300         /* If fid is already there return NULL */
301         BUG_ON(f->clunked);
302         if (f->fid == fid) {
303             return NULL;
304         }
305     }
306     f = g_malloc0(sizeof(V9fsFidState));
307     f->fid = fid;
308     f->fid_type = P9_FID_NONE;
309     f->ref = 1;
310     /*
311      * Mark the fid as referenced so that the LRU
312      * reclaim won't close the file descriptor
313      */
314     f->flags |= FID_REFERENCED;
315     f->next = s->fid_list;
316     s->fid_list = f;
317 
318     v9fs_readdir_init(&f->fs.dir);
319     v9fs_readdir_init(&f->fs_reclaim.dir);
320 
321     return f;
322 }
323 
324 static int coroutine_fn v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp)
325 {
326     int retval = 0;
327 
328     if (fidp->fs.xattr.copied_len == -1) {
329         /* getxattr/listxattr fid */
330         goto free_value;
331     }
332     /*
333      * if this is fid for setxattr. clunk should
334      * result in setxattr localcall
335      */
336     if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) {
337         /* clunk after partial write */
338         retval = -EINVAL;
339         goto free_out;
340     }
341     if (fidp->fs.xattr.len) {
342         retval = v9fs_co_lsetxattr(pdu, &fidp->path, &fidp->fs.xattr.name,
343                                    fidp->fs.xattr.value,
344                                    fidp->fs.xattr.len,
345                                    fidp->fs.xattr.flags);
346     } else {
347         retval = v9fs_co_lremovexattr(pdu, &fidp->path, &fidp->fs.xattr.name);
348     }
349 free_out:
350     v9fs_string_free(&fidp->fs.xattr.name);
351 free_value:
352     g_free(fidp->fs.xattr.value);
353     return retval;
354 }
355 
356 static int coroutine_fn free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
357 {
358     int retval = 0;
359 
360     if (fidp->fid_type == P9_FID_FILE) {
361         /* If we reclaimed the fd no need to close */
362         if (fidp->fs.fd != -1) {
363             retval = v9fs_co_close(pdu, &fidp->fs);
364         }
365     } else if (fidp->fid_type == P9_FID_DIR) {
366         if (fidp->fs.dir.stream != NULL) {
367             retval = v9fs_co_closedir(pdu, &fidp->fs);
368         }
369     } else if (fidp->fid_type == P9_FID_XATTR) {
370         retval = v9fs_xattr_fid_clunk(pdu, fidp);
371     }
372     v9fs_path_free(&fidp->path);
373     g_free(fidp);
374     return retval;
375 }
376 
377 static int coroutine_fn put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
378 {
379     BUG_ON(!fidp->ref);
380     fidp->ref--;
381     /*
382      * Don't free the fid if it is in reclaim list
383      */
384     if (!fidp->ref && fidp->clunked) {
385         if (fidp->fid == pdu->s->root_fid) {
386             /*
387              * if the clunked fid is root fid then we
388              * have unmounted the fs on the client side.
389              * delete the migration blocker. Ideally, this
390              * should be hooked to transport close notification
391              */
392             if (pdu->s->migration_blocker) {
393                 migrate_del_blocker(pdu->s->migration_blocker);
394                 error_free(pdu->s->migration_blocker);
395                 pdu->s->migration_blocker = NULL;
396             }
397         }
398         return free_fid(pdu, fidp);
399     }
400     return 0;
401 }
402 
403 static V9fsFidState *clunk_fid(V9fsState *s, int32_t fid)
404 {
405     V9fsFidState **fidpp, *fidp;
406 
407     for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
408         if ((*fidpp)->fid == fid) {
409             break;
410         }
411     }
412     if (*fidpp == NULL) {
413         return NULL;
414     }
415     fidp = *fidpp;
416     *fidpp = fidp->next;
417     fidp->clunked = 1;
418     return fidp;
419 }
420 
421 void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu)
422 {
423     int reclaim_count = 0;
424     V9fsState *s = pdu->s;
425     V9fsFidState *f, *reclaim_list = NULL;
426 
427     for (f = s->fid_list; f; f = f->next) {
428         /*
429          * Unlink fids cannot be reclaimed. Check
430          * for them and skip them. Also skip fids
431          * currently being operated on.
432          */
433         if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
434             continue;
435         }
436         /*
437          * if it is a recently referenced fid
438          * we leave the fid untouched and clear the
439          * reference bit. We come back to it later
440          * in the next iteration. (a simple LRU without
441          * moving list elements around)
442          */
443         if (f->flags & FID_REFERENCED) {
444             f->flags &= ~FID_REFERENCED;
445             continue;
446         }
447         /*
448          * Add fids to reclaim list.
449          */
450         if (f->fid_type == P9_FID_FILE) {
451             if (f->fs.fd != -1) {
452                 /*
453                  * Up the reference count so that
454                  * a clunk request won't free this fid
455                  */
456                 f->ref++;
457                 f->rclm_lst = reclaim_list;
458                 reclaim_list = f;
459                 f->fs_reclaim.fd = f->fs.fd;
460                 f->fs.fd = -1;
461                 reclaim_count++;
462             }
463         } else if (f->fid_type == P9_FID_DIR) {
464             if (f->fs.dir.stream != NULL) {
465                 /*
466                  * Up the reference count so that
467                  * a clunk request won't free this fid
468                  */
469                 f->ref++;
470                 f->rclm_lst = reclaim_list;
471                 reclaim_list = f;
472                 f->fs_reclaim.dir.stream = f->fs.dir.stream;
473                 f->fs.dir.stream = NULL;
474                 reclaim_count++;
475             }
476         }
477         if (reclaim_count >= open_fd_rc) {
478             break;
479         }
480     }
481     /*
482      * Now close the fid in reclaim list. Free them if they
483      * are already clunked.
484      */
485     while (reclaim_list) {
486         f = reclaim_list;
487         reclaim_list = f->rclm_lst;
488         if (f->fid_type == P9_FID_FILE) {
489             v9fs_co_close(pdu, &f->fs_reclaim);
490         } else if (f->fid_type == P9_FID_DIR) {
491             v9fs_co_closedir(pdu, &f->fs_reclaim);
492         }
493         f->rclm_lst = NULL;
494         /*
495          * Now drop the fid reference, free it
496          * if clunked.
497          */
498         put_fid(pdu, f);
499     }
500 }
501 
502 static int coroutine_fn v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path)
503 {
504     int err;
505     V9fsState *s = pdu->s;
506     V9fsFidState *fidp, head_fid;
507 
508     head_fid.next = s->fid_list;
509     for (fidp = s->fid_list; fidp; fidp = fidp->next) {
510         if (fidp->path.size != path->size) {
511             continue;
512         }
513         if (!memcmp(fidp->path.data, path->data, path->size)) {
514             /* Mark the fid non reclaimable. */
515             fidp->flags |= FID_NON_RECLAIMABLE;
516 
517             /* reopen the file/dir if already closed */
518             err = v9fs_reopen_fid(pdu, fidp);
519             if (err < 0) {
520                 return -1;
521             }
522             /*
523              * Go back to head of fid list because
524              * the list could have got updated when
525              * switched to the worker thread
526              */
527             if (err == 0) {
528                 fidp = &head_fid;
529             }
530         }
531     }
532     return 0;
533 }
534 
535 static void coroutine_fn virtfs_reset(V9fsPDU *pdu)
536 {
537     V9fsState *s = pdu->s;
538     V9fsFidState *fidp = NULL;
539 
540     /* Free all fids */
541     while (s->fid_list) {
542         fidp = s->fid_list;
543         s->fid_list = fidp->next;
544 
545         if (fidp->ref) {
546             fidp->clunked = 1;
547         } else {
548             free_fid(pdu, fidp);
549         }
550     }
551     if (fidp) {
552         /* One or more unclunked fids found... */
553         error_report("9pfs:%s: One or more uncluncked fids "
554                      "found during reset", __func__);
555     }
556 }
557 
558 #define P9_QID_TYPE_DIR         0x80
559 #define P9_QID_TYPE_SYMLINK     0x02
560 
561 #define P9_STAT_MODE_DIR        0x80000000
562 #define P9_STAT_MODE_APPEND     0x40000000
563 #define P9_STAT_MODE_EXCL       0x20000000
564 #define P9_STAT_MODE_MOUNT      0x10000000
565 #define P9_STAT_MODE_AUTH       0x08000000
566 #define P9_STAT_MODE_TMP        0x04000000
567 #define P9_STAT_MODE_SYMLINK    0x02000000
568 #define P9_STAT_MODE_LINK       0x01000000
569 #define P9_STAT_MODE_DEVICE     0x00800000
570 #define P9_STAT_MODE_NAMED_PIPE 0x00200000
571 #define P9_STAT_MODE_SOCKET     0x00100000
572 #define P9_STAT_MODE_SETUID     0x00080000
573 #define P9_STAT_MODE_SETGID     0x00040000
574 #define P9_STAT_MODE_SETVTX     0x00010000
575 
576 #define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR |          \
577                                 P9_STAT_MODE_SYMLINK |      \
578                                 P9_STAT_MODE_LINK |         \
579                                 P9_STAT_MODE_DEVICE |       \
580                                 P9_STAT_MODE_NAMED_PIPE |   \
581                                 P9_STAT_MODE_SOCKET)
582 
583 /* This is the algorithm from ufs in spfs */
584 static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
585 {
586     size_t size;
587 
588     memset(&qidp->path, 0, sizeof(qidp->path));
589     size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path));
590     memcpy(&qidp->path, &stbuf->st_ino, size);
591     qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
592     qidp->type = 0;
593     if (S_ISDIR(stbuf->st_mode)) {
594         qidp->type |= P9_QID_TYPE_DIR;
595     }
596     if (S_ISLNK(stbuf->st_mode)) {
597         qidp->type |= P9_QID_TYPE_SYMLINK;
598     }
599 }
600 
601 static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp,
602                                    V9fsQID *qidp)
603 {
604     struct stat stbuf;
605     int err;
606 
607     err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
608     if (err < 0) {
609         return err;
610     }
611     stat_to_qid(&stbuf, qidp);
612     return 0;
613 }
614 
615 V9fsPDU *pdu_alloc(V9fsState *s)
616 {
617     V9fsPDU *pdu = NULL;
618 
619     if (!QLIST_EMPTY(&s->free_list)) {
620         pdu = QLIST_FIRST(&s->free_list);
621         QLIST_REMOVE(pdu, next);
622         QLIST_INSERT_HEAD(&s->active_list, pdu, next);
623     }
624     return pdu;
625 }
626 
627 void pdu_free(V9fsPDU *pdu)
628 {
629     V9fsState *s = pdu->s;
630 
631     g_assert(!pdu->cancelled);
632     QLIST_REMOVE(pdu, next);
633     QLIST_INSERT_HEAD(&s->free_list, pdu, next);
634 }
635 
636 /*
637  * We don't do error checking for pdu_marshal/unmarshal here
638  * because we always expect to have enough space to encode
639  * error details
640  */
641 static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
642 {
643     int8_t id = pdu->id + 1; /* Response */
644     V9fsState *s = pdu->s;
645 
646     if (len < 0) {
647         int err = -len;
648         len = 7;
649 
650         if (s->proto_version != V9FS_PROTO_2000L) {
651             V9fsString str;
652 
653             str.data = strerror(err);
654             str.size = strlen(str.data);
655 
656             len += pdu_marshal(pdu, len, "s", &str);
657             id = P9_RERROR;
658         }
659 
660         len += pdu_marshal(pdu, len, "d", err);
661 
662         if (s->proto_version == V9FS_PROTO_2000L) {
663             id = P9_RLERROR;
664         }
665         trace_v9fs_rerror(pdu->tag, pdu->id, err); /* Trace ERROR */
666     }
667 
668     /* fill out the header */
669     pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
670 
671     /* keep these in sync */
672     pdu->size = len;
673     pdu->id = id;
674 
675     pdu_push_and_notify(pdu);
676 
677     /* Now wakeup anybody waiting in flush for this request */
678     if (!qemu_co_queue_next(&pdu->complete)) {
679         pdu_free(pdu);
680     }
681 }
682 
683 static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
684 {
685     mode_t ret;
686 
687     ret = mode & 0777;
688     if (mode & P9_STAT_MODE_DIR) {
689         ret |= S_IFDIR;
690     }
691 
692     if (mode & P9_STAT_MODE_SYMLINK) {
693         ret |= S_IFLNK;
694     }
695     if (mode & P9_STAT_MODE_SOCKET) {
696         ret |= S_IFSOCK;
697     }
698     if (mode & P9_STAT_MODE_NAMED_PIPE) {
699         ret |= S_IFIFO;
700     }
701     if (mode & P9_STAT_MODE_DEVICE) {
702         if (extension->size && extension->data[0] == 'c') {
703             ret |= S_IFCHR;
704         } else {
705             ret |= S_IFBLK;
706         }
707     }
708 
709     if (!(ret&~0777)) {
710         ret |= S_IFREG;
711     }
712 
713     if (mode & P9_STAT_MODE_SETUID) {
714         ret |= S_ISUID;
715     }
716     if (mode & P9_STAT_MODE_SETGID) {
717         ret |= S_ISGID;
718     }
719     if (mode & P9_STAT_MODE_SETVTX) {
720         ret |= S_ISVTX;
721     }
722 
723     return ret;
724 }
725 
726 static int donttouch_stat(V9fsStat *stat)
727 {
728     if (stat->type == -1 &&
729         stat->dev == -1 &&
730         stat->qid.type == -1 &&
731         stat->qid.version == -1 &&
732         stat->qid.path == -1 &&
733         stat->mode == -1 &&
734         stat->atime == -1 &&
735         stat->mtime == -1 &&
736         stat->length == -1 &&
737         !stat->name.size &&
738         !stat->uid.size &&
739         !stat->gid.size &&
740         !stat->muid.size &&
741         stat->n_uid == -1 &&
742         stat->n_gid == -1 &&
743         stat->n_muid == -1) {
744         return 1;
745     }
746 
747     return 0;
748 }
749 
750 static void v9fs_stat_init(V9fsStat *stat)
751 {
752     v9fs_string_init(&stat->name);
753     v9fs_string_init(&stat->uid);
754     v9fs_string_init(&stat->gid);
755     v9fs_string_init(&stat->muid);
756     v9fs_string_init(&stat->extension);
757 }
758 
759 static void v9fs_stat_free(V9fsStat *stat)
760 {
761     v9fs_string_free(&stat->name);
762     v9fs_string_free(&stat->uid);
763     v9fs_string_free(&stat->gid);
764     v9fs_string_free(&stat->muid);
765     v9fs_string_free(&stat->extension);
766 }
767 
768 static uint32_t stat_to_v9mode(const struct stat *stbuf)
769 {
770     uint32_t mode;
771 
772     mode = stbuf->st_mode & 0777;
773     if (S_ISDIR(stbuf->st_mode)) {
774         mode |= P9_STAT_MODE_DIR;
775     }
776 
777     if (S_ISLNK(stbuf->st_mode)) {
778         mode |= P9_STAT_MODE_SYMLINK;
779     }
780 
781     if (S_ISSOCK(stbuf->st_mode)) {
782         mode |= P9_STAT_MODE_SOCKET;
783     }
784 
785     if (S_ISFIFO(stbuf->st_mode)) {
786         mode |= P9_STAT_MODE_NAMED_PIPE;
787     }
788 
789     if (S_ISBLK(stbuf->st_mode) || S_ISCHR(stbuf->st_mode)) {
790         mode |= P9_STAT_MODE_DEVICE;
791     }
792 
793     if (stbuf->st_mode & S_ISUID) {
794         mode |= P9_STAT_MODE_SETUID;
795     }
796 
797     if (stbuf->st_mode & S_ISGID) {
798         mode |= P9_STAT_MODE_SETGID;
799     }
800 
801     if (stbuf->st_mode & S_ISVTX) {
802         mode |= P9_STAT_MODE_SETVTX;
803     }
804 
805     return mode;
806 }
807 
808 static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
809                                        const struct stat *stbuf,
810                                        V9fsStat *v9stat)
811 {
812     int err;
813     const char *str;
814 
815     memset(v9stat, 0, sizeof(*v9stat));
816 
817     stat_to_qid(stbuf, &v9stat->qid);
818     v9stat->mode = stat_to_v9mode(stbuf);
819     v9stat->atime = stbuf->st_atime;
820     v9stat->mtime = stbuf->st_mtime;
821     v9stat->length = stbuf->st_size;
822 
823     v9fs_string_free(&v9stat->uid);
824     v9fs_string_free(&v9stat->gid);
825     v9fs_string_free(&v9stat->muid);
826 
827     v9stat->n_uid = stbuf->st_uid;
828     v9stat->n_gid = stbuf->st_gid;
829     v9stat->n_muid = 0;
830 
831     v9fs_string_free(&v9stat->extension);
832 
833     if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
834         err = v9fs_co_readlink(pdu, name, &v9stat->extension);
835         if (err < 0) {
836             return err;
837         }
838     } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
839         v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
840                 S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
841                 major(stbuf->st_rdev), minor(stbuf->st_rdev));
842     } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
843         v9fs_string_sprintf(&v9stat->extension, "%s %lu",
844                 "HARDLINKCOUNT", (unsigned long)stbuf->st_nlink);
845     }
846 
847     str = strrchr(name->data, '/');
848     if (str) {
849         str += 1;
850     } else {
851         str = name->data;
852     }
853 
854     v9fs_string_sprintf(&v9stat->name, "%s", str);
855 
856     v9stat->size = 61 +
857         v9fs_string_size(&v9stat->name) +
858         v9fs_string_size(&v9stat->uid) +
859         v9fs_string_size(&v9stat->gid) +
860         v9fs_string_size(&v9stat->muid) +
861         v9fs_string_size(&v9stat->extension);
862     return 0;
863 }
864 
865 #define P9_STATS_MODE          0x00000001ULL
866 #define P9_STATS_NLINK         0x00000002ULL
867 #define P9_STATS_UID           0x00000004ULL
868 #define P9_STATS_GID           0x00000008ULL
869 #define P9_STATS_RDEV          0x00000010ULL
870 #define P9_STATS_ATIME         0x00000020ULL
871 #define P9_STATS_MTIME         0x00000040ULL
872 #define P9_STATS_CTIME         0x00000080ULL
873 #define P9_STATS_INO           0x00000100ULL
874 #define P9_STATS_SIZE          0x00000200ULL
875 #define P9_STATS_BLOCKS        0x00000400ULL
876 
877 #define P9_STATS_BTIME         0x00000800ULL
878 #define P9_STATS_GEN           0x00001000ULL
879 #define P9_STATS_DATA_VERSION  0x00002000ULL
880 
881 #define P9_STATS_BASIC         0x000007ffULL /* Mask for fields up to BLOCKS */
882 #define P9_STATS_ALL           0x00003fffULL /* Mask for All fields above */
883 
884 
885 static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf,
886                                 V9fsStatDotl *v9lstat)
887 {
888     memset(v9lstat, 0, sizeof(*v9lstat));
889 
890     v9lstat->st_mode = stbuf->st_mode;
891     v9lstat->st_nlink = stbuf->st_nlink;
892     v9lstat->st_uid = stbuf->st_uid;
893     v9lstat->st_gid = stbuf->st_gid;
894     v9lstat->st_rdev = stbuf->st_rdev;
895     v9lstat->st_size = stbuf->st_size;
896     v9lstat->st_blksize = stbuf->st_blksize;
897     v9lstat->st_blocks = stbuf->st_blocks;
898     v9lstat->st_atime_sec = stbuf->st_atime;
899     v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
900     v9lstat->st_mtime_sec = stbuf->st_mtime;
901     v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
902     v9lstat->st_ctime_sec = stbuf->st_ctime;
903     v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec;
904     /* Currently we only support BASIC fields in stat */
905     v9lstat->st_result_mask = P9_STATS_BASIC;
906 
907     stat_to_qid(stbuf, &v9lstat->qid);
908 }
909 
910 static void print_sg(struct iovec *sg, int cnt)
911 {
912     int i;
913 
914     printf("sg[%d]: {", cnt);
915     for (i = 0; i < cnt; i++) {
916         if (i) {
917             printf(", ");
918         }
919         printf("(%p, %zd)", sg[i].iov_base, sg[i].iov_len);
920     }
921     printf("}\n");
922 }
923 
924 /* Will call this only for path name based fid */
925 static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len)
926 {
927     V9fsPath str;
928     v9fs_path_init(&str);
929     v9fs_path_copy(&str, dst);
930     v9fs_path_sprintf(dst, "%s%s", src->data, str.data + len);
931     v9fs_path_free(&str);
932 }
933 
934 static inline bool is_ro_export(FsContext *ctx)
935 {
936     return ctx->export_flags & V9FS_RDONLY;
937 }
938 
939 static void coroutine_fn v9fs_version(void *opaque)
940 {
941     ssize_t err;
942     V9fsPDU *pdu = opaque;
943     V9fsState *s = pdu->s;
944     V9fsString version;
945     size_t offset = 7;
946 
947     v9fs_string_init(&version);
948     err = pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
949     if (err < 0) {
950         offset = err;
951         goto out;
952     }
953     trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
954 
955     virtfs_reset(pdu);
956 
957     if (!strcmp(version.data, "9P2000.u")) {
958         s->proto_version = V9FS_PROTO_2000U;
959     } else if (!strcmp(version.data, "9P2000.L")) {
960         s->proto_version = V9FS_PROTO_2000L;
961     } else {
962         v9fs_string_sprintf(&version, "unknown");
963     }
964 
965     err = pdu_marshal(pdu, offset, "ds", s->msize, &version);
966     if (err < 0) {
967         offset = err;
968         goto out;
969     }
970     offset += err;
971     trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data);
972 out:
973     pdu_complete(pdu, offset);
974     v9fs_string_free(&version);
975 }
976 
977 static void coroutine_fn v9fs_attach(void *opaque)
978 {
979     V9fsPDU *pdu = opaque;
980     V9fsState *s = pdu->s;
981     int32_t fid, afid, n_uname;
982     V9fsString uname, aname;
983     V9fsFidState *fidp;
984     size_t offset = 7;
985     V9fsQID qid;
986     ssize_t err;
987 
988     v9fs_string_init(&uname);
989     v9fs_string_init(&aname);
990     err = pdu_unmarshal(pdu, offset, "ddssd", &fid,
991                         &afid, &uname, &aname, &n_uname);
992     if (err < 0) {
993         goto out_nofid;
994     }
995     trace_v9fs_attach(pdu->tag, pdu->id, fid, afid, uname.data, aname.data);
996 
997     fidp = alloc_fid(s, fid);
998     if (fidp == NULL) {
999         err = -EINVAL;
1000         goto out_nofid;
1001     }
1002     fidp->uid = n_uname;
1003     err = v9fs_co_name_to_path(pdu, NULL, "/", &fidp->path);
1004     if (err < 0) {
1005         err = -EINVAL;
1006         clunk_fid(s, fid);
1007         goto out;
1008     }
1009     err = fid_to_qid(pdu, fidp, &qid);
1010     if (err < 0) {
1011         err = -EINVAL;
1012         clunk_fid(s, fid);
1013         goto out;
1014     }
1015     err = pdu_marshal(pdu, offset, "Q", &qid);
1016     if (err < 0) {
1017         clunk_fid(s, fid);
1018         goto out;
1019     }
1020     err += offset;
1021     memcpy(&s->root_qid, &qid, sizeof(qid));
1022     trace_v9fs_attach_return(pdu->tag, pdu->id,
1023                              qid.type, qid.version, qid.path);
1024     /*
1025      * disable migration if we haven't done already.
1026      * attach could get called multiple times for the same export.
1027      */
1028     if (!s->migration_blocker) {
1029         s->root_fid = fid;
1030         error_setg(&s->migration_blocker,
1031                    "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'",
1032                    s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
1033         migrate_add_blocker(s->migration_blocker);
1034     }
1035 out:
1036     put_fid(pdu, fidp);
1037 out_nofid:
1038     pdu_complete(pdu, err);
1039     v9fs_string_free(&uname);
1040     v9fs_string_free(&aname);
1041 }
1042 
1043 static void coroutine_fn v9fs_stat(void *opaque)
1044 {
1045     int32_t fid;
1046     V9fsStat v9stat;
1047     ssize_t err = 0;
1048     size_t offset = 7;
1049     struct stat stbuf;
1050     V9fsFidState *fidp;
1051     V9fsPDU *pdu = opaque;
1052 
1053     err = pdu_unmarshal(pdu, offset, "d", &fid);
1054     if (err < 0) {
1055         goto out_nofid;
1056     }
1057     trace_v9fs_stat(pdu->tag, pdu->id, fid);
1058 
1059     fidp = get_fid(pdu, fid);
1060     if (fidp == NULL) {
1061         err = -ENOENT;
1062         goto out_nofid;
1063     }
1064     err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
1065     if (err < 0) {
1066         goto out;
1067     }
1068     err = stat_to_v9stat(pdu, &fidp->path, &stbuf, &v9stat);
1069     if (err < 0) {
1070         goto out;
1071     }
1072     err = pdu_marshal(pdu, offset, "wS", 0, &v9stat);
1073     if (err < 0) {
1074         v9fs_stat_free(&v9stat);
1075         goto out;
1076     }
1077     trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode,
1078                            v9stat.atime, v9stat.mtime, v9stat.length);
1079     err += offset;
1080     v9fs_stat_free(&v9stat);
1081 out:
1082     put_fid(pdu, fidp);
1083 out_nofid:
1084     pdu_complete(pdu, err);
1085 }
1086 
1087 static void coroutine_fn v9fs_getattr(void *opaque)
1088 {
1089     int32_t fid;
1090     size_t offset = 7;
1091     ssize_t retval = 0;
1092     struct stat stbuf;
1093     V9fsFidState *fidp;
1094     uint64_t request_mask;
1095     V9fsStatDotl v9stat_dotl;
1096     V9fsPDU *pdu = opaque;
1097     V9fsState *s = pdu->s;
1098 
1099     retval = pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
1100     if (retval < 0) {
1101         goto out_nofid;
1102     }
1103     trace_v9fs_getattr(pdu->tag, pdu->id, fid, request_mask);
1104 
1105     fidp = get_fid(pdu, fid);
1106     if (fidp == NULL) {
1107         retval = -ENOENT;
1108         goto out_nofid;
1109     }
1110     /*
1111      * Currently we only support BASIC fields in stat, so there is no
1112      * need to look at request_mask.
1113      */
1114     retval = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
1115     if (retval < 0) {
1116         goto out;
1117     }
1118     stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl);
1119 
1120     /*  fill st_gen if requested and supported by underlying fs */
1121     if (request_mask & P9_STATS_GEN) {
1122         retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl);
1123         switch (retval) {
1124         case 0:
1125             /* we have valid st_gen: update result mask */
1126             v9stat_dotl.st_result_mask |= P9_STATS_GEN;
1127             break;
1128         case -EINTR:
1129             /* request cancelled, e.g. by Tflush */
1130             goto out;
1131         default:
1132             /* failed to get st_gen: not fatal, ignore */
1133             break;
1134         }
1135     }
1136     retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl);
1137     if (retval < 0) {
1138         goto out;
1139     }
1140     retval += offset;
1141     trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask,
1142                               v9stat_dotl.st_mode, v9stat_dotl.st_uid,
1143                               v9stat_dotl.st_gid);
1144 out:
1145     put_fid(pdu, fidp);
1146 out_nofid:
1147     pdu_complete(pdu, retval);
1148 }
1149 
1150 /* Attribute flags */
1151 #define P9_ATTR_MODE       (1 << 0)
1152 #define P9_ATTR_UID        (1 << 1)
1153 #define P9_ATTR_GID        (1 << 2)
1154 #define P9_ATTR_SIZE       (1 << 3)
1155 #define P9_ATTR_ATIME      (1 << 4)
1156 #define P9_ATTR_MTIME      (1 << 5)
1157 #define P9_ATTR_CTIME      (1 << 6)
1158 #define P9_ATTR_ATIME_SET  (1 << 7)
1159 #define P9_ATTR_MTIME_SET  (1 << 8)
1160 
1161 #define P9_ATTR_MASK    127
1162 
1163 static void coroutine_fn v9fs_setattr(void *opaque)
1164 {
1165     int err = 0;
1166     int32_t fid;
1167     V9fsFidState *fidp;
1168     size_t offset = 7;
1169     V9fsIattr v9iattr;
1170     V9fsPDU *pdu = opaque;
1171 
1172     err = pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
1173     if (err < 0) {
1174         goto out_nofid;
1175     }
1176 
1177     fidp = get_fid(pdu, fid);
1178     if (fidp == NULL) {
1179         err = -EINVAL;
1180         goto out_nofid;
1181     }
1182     if (v9iattr.valid & P9_ATTR_MODE) {
1183         err = v9fs_co_chmod(pdu, &fidp->path, v9iattr.mode);
1184         if (err < 0) {
1185             goto out;
1186         }
1187     }
1188     if (v9iattr.valid & (P9_ATTR_ATIME | P9_ATTR_MTIME)) {
1189         struct timespec times[2];
1190         if (v9iattr.valid & P9_ATTR_ATIME) {
1191             if (v9iattr.valid & P9_ATTR_ATIME_SET) {
1192                 times[0].tv_sec = v9iattr.atime_sec;
1193                 times[0].tv_nsec = v9iattr.atime_nsec;
1194             } else {
1195                 times[0].tv_nsec = UTIME_NOW;
1196             }
1197         } else {
1198             times[0].tv_nsec = UTIME_OMIT;
1199         }
1200         if (v9iattr.valid & P9_ATTR_MTIME) {
1201             if (v9iattr.valid & P9_ATTR_MTIME_SET) {
1202                 times[1].tv_sec = v9iattr.mtime_sec;
1203                 times[1].tv_nsec = v9iattr.mtime_nsec;
1204             } else {
1205                 times[1].tv_nsec = UTIME_NOW;
1206             }
1207         } else {
1208             times[1].tv_nsec = UTIME_OMIT;
1209         }
1210         err = v9fs_co_utimensat(pdu, &fidp->path, times);
1211         if (err < 0) {
1212             goto out;
1213         }
1214     }
1215     /*
1216      * If the only valid entry in iattr is ctime we can call
1217      * chown(-1,-1) to update the ctime of the file
1218      */
1219     if ((v9iattr.valid & (P9_ATTR_UID | P9_ATTR_GID)) ||
1220         ((v9iattr.valid & P9_ATTR_CTIME)
1221          && !((v9iattr.valid & P9_ATTR_MASK) & ~P9_ATTR_CTIME))) {
1222         if (!(v9iattr.valid & P9_ATTR_UID)) {
1223             v9iattr.uid = -1;
1224         }
1225         if (!(v9iattr.valid & P9_ATTR_GID)) {
1226             v9iattr.gid = -1;
1227         }
1228         err = v9fs_co_chown(pdu, &fidp->path, v9iattr.uid,
1229                             v9iattr.gid);
1230         if (err < 0) {
1231             goto out;
1232         }
1233     }
1234     if (v9iattr.valid & (P9_ATTR_SIZE)) {
1235         err = v9fs_co_truncate(pdu, &fidp->path, v9iattr.size);
1236         if (err < 0) {
1237             goto out;
1238         }
1239     }
1240     err = offset;
1241 out:
1242     put_fid(pdu, fidp);
1243 out_nofid:
1244     pdu_complete(pdu, err);
1245 }
1246 
1247 static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
1248 {
1249     int i;
1250     ssize_t err;
1251     size_t offset = 7;
1252 
1253     err = pdu_marshal(pdu, offset, "w", nwnames);
1254     if (err < 0) {
1255         return err;
1256     }
1257     offset += err;
1258     for (i = 0; i < nwnames; i++) {
1259         err = pdu_marshal(pdu, offset, "Q", &qids[i]);
1260         if (err < 0) {
1261             return err;
1262         }
1263         offset += err;
1264     }
1265     return offset;
1266 }
1267 
1268 static bool name_is_illegal(const char *name)
1269 {
1270     return !*name || strchr(name, '/') != NULL;
1271 }
1272 
1273 static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2)
1274 {
1275     return
1276         qid1->type != qid2->type ||
1277         qid1->version != qid2->version ||
1278         qid1->path != qid2->path;
1279 }
1280 
1281 static void coroutine_fn v9fs_walk(void *opaque)
1282 {
1283     int name_idx;
1284     V9fsQID *qids = NULL;
1285     int i, err = 0;
1286     V9fsPath dpath, path;
1287     uint16_t nwnames;
1288     struct stat stbuf;
1289     size_t offset = 7;
1290     int32_t fid, newfid;
1291     V9fsString *wnames = NULL;
1292     V9fsFidState *fidp;
1293     V9fsFidState *newfidp = NULL;
1294     V9fsPDU *pdu = opaque;
1295     V9fsState *s = pdu->s;
1296     V9fsQID qid;
1297 
1298     err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
1299     if (err < 0) {
1300         pdu_complete(pdu, err);
1301         return ;
1302     }
1303     offset += err;
1304 
1305     trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames);
1306 
1307     if (nwnames && nwnames <= P9_MAXWELEM) {
1308         wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
1309         qids   = g_malloc0(sizeof(qids[0]) * nwnames);
1310         for (i = 0; i < nwnames; i++) {
1311             err = pdu_unmarshal(pdu, offset, "s", &wnames[i]);
1312             if (err < 0) {
1313                 goto out_nofid;
1314             }
1315             if (name_is_illegal(wnames[i].data)) {
1316                 err = -ENOENT;
1317                 goto out_nofid;
1318             }
1319             offset += err;
1320         }
1321     } else if (nwnames > P9_MAXWELEM) {
1322         err = -EINVAL;
1323         goto out_nofid;
1324     }
1325     fidp = get_fid(pdu, fid);
1326     if (fidp == NULL) {
1327         err = -ENOENT;
1328         goto out_nofid;
1329     }
1330 
1331     v9fs_path_init(&dpath);
1332     v9fs_path_init(&path);
1333 
1334     err = fid_to_qid(pdu, fidp, &qid);
1335     if (err < 0) {
1336         goto out;
1337     }
1338 
1339     /*
1340      * Both dpath and path initially poin to fidp.
1341      * Needed to handle request with nwnames == 0
1342      */
1343     v9fs_path_copy(&dpath, &fidp->path);
1344     v9fs_path_copy(&path, &fidp->path);
1345     for (name_idx = 0; name_idx < nwnames; name_idx++) {
1346         if (not_same_qid(&pdu->s->root_qid, &qid) ||
1347             strcmp("..", wnames[name_idx].data)) {
1348             err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data,
1349                                        &path);
1350             if (err < 0) {
1351                 goto out;
1352             }
1353 
1354             err = v9fs_co_lstat(pdu, &path, &stbuf);
1355             if (err < 0) {
1356                 goto out;
1357             }
1358             stat_to_qid(&stbuf, &qid);
1359             v9fs_path_copy(&dpath, &path);
1360         }
1361         memcpy(&qids[name_idx], &qid, sizeof(qid));
1362     }
1363     if (fid == newfid) {
1364         BUG_ON(fidp->fid_type != P9_FID_NONE);
1365         v9fs_path_copy(&fidp->path, &path);
1366     } else {
1367         newfidp = alloc_fid(s, newfid);
1368         if (newfidp == NULL) {
1369             err = -EINVAL;
1370             goto out;
1371         }
1372         newfidp->uid = fidp->uid;
1373         v9fs_path_copy(&newfidp->path, &path);
1374     }
1375     err = v9fs_walk_marshal(pdu, nwnames, qids);
1376     trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids);
1377 out:
1378     put_fid(pdu, fidp);
1379     if (newfidp) {
1380         put_fid(pdu, newfidp);
1381     }
1382     v9fs_path_free(&dpath);
1383     v9fs_path_free(&path);
1384 out_nofid:
1385     pdu_complete(pdu, err);
1386     if (nwnames && nwnames <= P9_MAXWELEM) {
1387         for (name_idx = 0; name_idx < nwnames; name_idx++) {
1388             v9fs_string_free(&wnames[name_idx]);
1389         }
1390         g_free(wnames);
1391         g_free(qids);
1392     }
1393 }
1394 
1395 static int32_t coroutine_fn get_iounit(V9fsPDU *pdu, V9fsPath *path)
1396 {
1397     struct statfs stbuf;
1398     int32_t iounit = 0;
1399     V9fsState *s = pdu->s;
1400 
1401     /*
1402      * iounit should be multiples of f_bsize (host filesystem block size
1403      * and as well as less than (client msize - P9_IOHDRSZ))
1404      */
1405     if (!v9fs_co_statfs(pdu, path, &stbuf)) {
1406         iounit = stbuf.f_bsize;
1407         iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
1408     }
1409     if (!iounit) {
1410         iounit = s->msize - P9_IOHDRSZ;
1411     }
1412     return iounit;
1413 }
1414 
1415 static void coroutine_fn v9fs_open(void *opaque)
1416 {
1417     int flags;
1418     int32_t fid;
1419     int32_t mode;
1420     V9fsQID qid;
1421     int iounit = 0;
1422     ssize_t err = 0;
1423     size_t offset = 7;
1424     struct stat stbuf;
1425     V9fsFidState *fidp;
1426     V9fsPDU *pdu = opaque;
1427     V9fsState *s = pdu->s;
1428 
1429     if (s->proto_version == V9FS_PROTO_2000L) {
1430         err = pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
1431     } else {
1432         uint8_t modebyte;
1433         err = pdu_unmarshal(pdu, offset, "db", &fid, &modebyte);
1434         mode = modebyte;
1435     }
1436     if (err < 0) {
1437         goto out_nofid;
1438     }
1439     trace_v9fs_open(pdu->tag, pdu->id, fid, mode);
1440 
1441     fidp = get_fid(pdu, fid);
1442     if (fidp == NULL) {
1443         err = -ENOENT;
1444         goto out_nofid;
1445     }
1446     BUG_ON(fidp->fid_type != P9_FID_NONE);
1447 
1448     err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
1449     if (err < 0) {
1450         goto out;
1451     }
1452     stat_to_qid(&stbuf, &qid);
1453     if (S_ISDIR(stbuf.st_mode)) {
1454         err = v9fs_co_opendir(pdu, fidp);
1455         if (err < 0) {
1456             goto out;
1457         }
1458         fidp->fid_type = P9_FID_DIR;
1459         err = pdu_marshal(pdu, offset, "Qd", &qid, 0);
1460         if (err < 0) {
1461             goto out;
1462         }
1463         err += offset;
1464     } else {
1465         if (s->proto_version == V9FS_PROTO_2000L) {
1466             flags = get_dotl_openflags(s, mode);
1467         } else {
1468             flags = omode_to_uflags(mode);
1469         }
1470         if (is_ro_export(&s->ctx)) {
1471             if (mode & O_WRONLY || mode & O_RDWR ||
1472                 mode & O_APPEND || mode & O_TRUNC) {
1473                 err = -EROFS;
1474                 goto out;
1475             }
1476         }
1477         err = v9fs_co_open(pdu, fidp, flags);
1478         if (err < 0) {
1479             goto out;
1480         }
1481         fidp->fid_type = P9_FID_FILE;
1482         fidp->open_flags = flags;
1483         if (flags & O_EXCL) {
1484             /*
1485              * We let the host file system do O_EXCL check
1486              * We should not reclaim such fd
1487              */
1488             fidp->flags |= FID_NON_RECLAIMABLE;
1489         }
1490         iounit = get_iounit(pdu, &fidp->path);
1491         err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
1492         if (err < 0) {
1493             goto out;
1494         }
1495         err += offset;
1496     }
1497     trace_v9fs_open_return(pdu->tag, pdu->id,
1498                            qid.type, qid.version, qid.path, iounit);
1499 out:
1500     put_fid(pdu, fidp);
1501 out_nofid:
1502     pdu_complete(pdu, err);
1503 }
1504 
1505 static void coroutine_fn v9fs_lcreate(void *opaque)
1506 {
1507     int32_t dfid, flags, mode;
1508     gid_t gid;
1509     ssize_t err = 0;
1510     ssize_t offset = 7;
1511     V9fsString name;
1512     V9fsFidState *fidp;
1513     struct stat stbuf;
1514     V9fsQID qid;
1515     int32_t iounit;
1516     V9fsPDU *pdu = opaque;
1517 
1518     v9fs_string_init(&name);
1519     err = pdu_unmarshal(pdu, offset, "dsddd", &dfid,
1520                         &name, &flags, &mode, &gid);
1521     if (err < 0) {
1522         goto out_nofid;
1523     }
1524     trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
1525 
1526     if (name_is_illegal(name.data)) {
1527         err = -ENOENT;
1528         goto out_nofid;
1529     }
1530 
1531     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
1532         err = -EEXIST;
1533         goto out_nofid;
1534     }
1535 
1536     fidp = get_fid(pdu, dfid);
1537     if (fidp == NULL) {
1538         err = -ENOENT;
1539         goto out_nofid;
1540     }
1541 
1542     flags = get_dotl_openflags(pdu->s, flags);
1543     err = v9fs_co_open2(pdu, fidp, &name, gid,
1544                         flags | O_CREAT, mode, &stbuf);
1545     if (err < 0) {
1546         goto out;
1547     }
1548     fidp->fid_type = P9_FID_FILE;
1549     fidp->open_flags = flags;
1550     if (flags & O_EXCL) {
1551         /*
1552          * We let the host file system do O_EXCL check
1553          * We should not reclaim such fd
1554          */
1555         fidp->flags |= FID_NON_RECLAIMABLE;
1556     }
1557     iounit =  get_iounit(pdu, &fidp->path);
1558     stat_to_qid(&stbuf, &qid);
1559     err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
1560     if (err < 0) {
1561         goto out;
1562     }
1563     err += offset;
1564     trace_v9fs_lcreate_return(pdu->tag, pdu->id,
1565                               qid.type, qid.version, qid.path, iounit);
1566 out:
1567     put_fid(pdu, fidp);
1568 out_nofid:
1569     pdu_complete(pdu, err);
1570     v9fs_string_free(&name);
1571 }
1572 
1573 static void v9fs_fsync(void *opaque)
1574 {
1575     int err;
1576     int32_t fid;
1577     int datasync;
1578     size_t offset = 7;
1579     V9fsFidState *fidp;
1580     V9fsPDU *pdu = opaque;
1581 
1582     err = pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
1583     if (err < 0) {
1584         goto out_nofid;
1585     }
1586     trace_v9fs_fsync(pdu->tag, pdu->id, fid, datasync);
1587 
1588     fidp = get_fid(pdu, fid);
1589     if (fidp == NULL) {
1590         err = -ENOENT;
1591         goto out_nofid;
1592     }
1593     err = v9fs_co_fsync(pdu, fidp, datasync);
1594     if (!err) {
1595         err = offset;
1596     }
1597     put_fid(pdu, fidp);
1598 out_nofid:
1599     pdu_complete(pdu, err);
1600 }
1601 
1602 static void coroutine_fn v9fs_clunk(void *opaque)
1603 {
1604     int err;
1605     int32_t fid;
1606     size_t offset = 7;
1607     V9fsFidState *fidp;
1608     V9fsPDU *pdu = opaque;
1609     V9fsState *s = pdu->s;
1610 
1611     err = pdu_unmarshal(pdu, offset, "d", &fid);
1612     if (err < 0) {
1613         goto out_nofid;
1614     }
1615     trace_v9fs_clunk(pdu->tag, pdu->id, fid);
1616 
1617     fidp = clunk_fid(s, fid);
1618     if (fidp == NULL) {
1619         err = -ENOENT;
1620         goto out_nofid;
1621     }
1622     /*
1623      * Bump the ref so that put_fid will
1624      * free the fid.
1625      */
1626     fidp->ref++;
1627     err = put_fid(pdu, fidp);
1628     if (!err) {
1629         err = offset;
1630     }
1631 out_nofid:
1632     pdu_complete(pdu, err);
1633 }
1634 
1635 static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
1636                            uint64_t off, uint32_t max_count)
1637 {
1638     ssize_t err;
1639     size_t offset = 7;
1640     int read_count;
1641     int64_t xattr_len;
1642     V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
1643     VirtQueueElement *elem = v->elems[pdu->idx];
1644 
1645     xattr_len = fidp->fs.xattr.len;
1646     read_count = xattr_len - off;
1647     if (read_count > max_count) {
1648         read_count = max_count;
1649     } else if (read_count < 0) {
1650         /*
1651          * read beyond XATTR value
1652          */
1653         read_count = 0;
1654     }
1655     err = pdu_marshal(pdu, offset, "d", read_count);
1656     if (err < 0) {
1657         return err;
1658     }
1659     offset += err;
1660 
1661     err = v9fs_pack(elem->in_sg, elem->in_num, offset,
1662                     ((char *)fidp->fs.xattr.value) + off,
1663                     read_count);
1664     if (err < 0) {
1665         return err;
1666     }
1667     offset += err;
1668     return offset;
1669 }
1670 
1671 static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
1672                                                   V9fsFidState *fidp,
1673                                                   uint32_t max_count)
1674 {
1675     V9fsPath path;
1676     V9fsStat v9stat;
1677     int len, err = 0;
1678     int32_t count = 0;
1679     struct stat stbuf;
1680     off_t saved_dir_pos;
1681     struct dirent *dent;
1682 
1683     /* save the directory position */
1684     saved_dir_pos = v9fs_co_telldir(pdu, fidp);
1685     if (saved_dir_pos < 0) {
1686         return saved_dir_pos;
1687     }
1688 
1689     while (1) {
1690         v9fs_path_init(&path);
1691 
1692         v9fs_readdir_lock(&fidp->fs.dir);
1693 
1694         err = v9fs_co_readdir(pdu, fidp, &dent);
1695         if (err || !dent) {
1696             break;
1697         }
1698         err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
1699         if (err < 0) {
1700             break;
1701         }
1702         err = v9fs_co_lstat(pdu, &path, &stbuf);
1703         if (err < 0) {
1704             break;
1705         }
1706         err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
1707         if (err < 0) {
1708             break;
1709         }
1710         /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
1711         len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
1712 
1713         v9fs_readdir_unlock(&fidp->fs.dir);
1714 
1715         if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
1716             /* Ran out of buffer. Set dir back to old position and return */
1717             v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
1718             v9fs_stat_free(&v9stat);
1719             v9fs_path_free(&path);
1720             return count;
1721         }
1722         count += len;
1723         v9fs_stat_free(&v9stat);
1724         v9fs_path_free(&path);
1725         saved_dir_pos = dent->d_off;
1726     }
1727 
1728     v9fs_readdir_unlock(&fidp->fs.dir);
1729 
1730     v9fs_path_free(&path);
1731     if (err < 0) {
1732         return err;
1733     }
1734     return count;
1735 }
1736 
1737 /*
1738  * Create a QEMUIOVector for a sub-region of PDU iovecs
1739  *
1740  * @qiov:       uninitialized QEMUIOVector
1741  * @skip:       number of bytes to skip from beginning of PDU
1742  * @size:       number of bytes to include
1743  * @is_write:   true - write, false - read
1744  *
1745  * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
1746  * with qemu_iovec_destroy().
1747  */
1748 static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
1749                                     size_t skip, size_t size,
1750                                     bool is_write)
1751 {
1752     QEMUIOVector elem;
1753     struct iovec *iov;
1754     unsigned int niov;
1755 
1756     virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write);
1757 
1758     qemu_iovec_init_external(&elem, iov, niov);
1759     qemu_iovec_init(qiov, niov);
1760     qemu_iovec_concat(qiov, &elem, skip, size);
1761 }
1762 
1763 static void coroutine_fn v9fs_read(void *opaque)
1764 {
1765     int32_t fid;
1766     uint64_t off;
1767     ssize_t err = 0;
1768     int32_t count = 0;
1769     size_t offset = 7;
1770     uint32_t max_count;
1771     V9fsFidState *fidp;
1772     V9fsPDU *pdu = opaque;
1773     V9fsState *s = pdu->s;
1774 
1775     err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
1776     if (err < 0) {
1777         goto out_nofid;
1778     }
1779     trace_v9fs_read(pdu->tag, pdu->id, fid, off, max_count);
1780 
1781     fidp = get_fid(pdu, fid);
1782     if (fidp == NULL) {
1783         err = -EINVAL;
1784         goto out_nofid;
1785     }
1786     if (fidp->fid_type == P9_FID_DIR) {
1787 
1788         if (off == 0) {
1789             v9fs_co_rewinddir(pdu, fidp);
1790         }
1791         count = v9fs_do_readdir_with_stat(pdu, fidp, max_count);
1792         if (count < 0) {
1793             err = count;
1794             goto out;
1795         }
1796         err = pdu_marshal(pdu, offset, "d", count);
1797         if (err < 0) {
1798             goto out;
1799         }
1800         err += offset + count;
1801     } else if (fidp->fid_type == P9_FID_FILE) {
1802         QEMUIOVector qiov_full;
1803         QEMUIOVector qiov;
1804         int32_t len;
1805 
1806         v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false);
1807         qemu_iovec_init(&qiov, qiov_full.niov);
1808         do {
1809             qemu_iovec_reset(&qiov);
1810             qemu_iovec_concat(&qiov, &qiov_full, count, qiov_full.size - count);
1811             if (0) {
1812                 print_sg(qiov.iov, qiov.niov);
1813             }
1814             /* Loop in case of EINTR */
1815             do {
1816                 len = v9fs_co_preadv(pdu, fidp, qiov.iov, qiov.niov, off);
1817                 if (len >= 0) {
1818                     off   += len;
1819                     count += len;
1820                 }
1821             } while (len == -EINTR && !pdu->cancelled);
1822             if (len < 0) {
1823                 /* IO error return the error */
1824                 err = len;
1825                 goto out_free_iovec;
1826             }
1827         } while (count < max_count && len > 0);
1828         err = pdu_marshal(pdu, offset, "d", count);
1829         if (err < 0) {
1830             goto out_free_iovec;
1831         }
1832         err += offset + count;
1833 out_free_iovec:
1834         qemu_iovec_destroy(&qiov);
1835         qemu_iovec_destroy(&qiov_full);
1836     } else if (fidp->fid_type == P9_FID_XATTR) {
1837         err = v9fs_xattr_read(s, pdu, fidp, off, max_count);
1838     } else {
1839         err = -EINVAL;
1840     }
1841     trace_v9fs_read_return(pdu->tag, pdu->id, count, err);
1842 out:
1843     put_fid(pdu, fidp);
1844 out_nofid:
1845     pdu_complete(pdu, err);
1846 }
1847 
1848 static size_t v9fs_readdir_data_size(V9fsString *name)
1849 {
1850     /*
1851      * Size of each dirent on the wire: size of qid (13) + size of offset (8)
1852      * size of type (1) + size of name.size (2) + strlen(name.data)
1853      */
1854     return 24 + v9fs_string_size(name);
1855 }
1856 
1857 static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
1858                                         int32_t max_count)
1859 {
1860     size_t size;
1861     V9fsQID qid;
1862     V9fsString name;
1863     int len, err = 0;
1864     int32_t count = 0;
1865     off_t saved_dir_pos;
1866     struct dirent *dent;
1867 
1868     /* save the directory position */
1869     saved_dir_pos = v9fs_co_telldir(pdu, fidp);
1870     if (saved_dir_pos < 0) {
1871         return saved_dir_pos;
1872     }
1873 
1874     while (1) {
1875         v9fs_readdir_lock(&fidp->fs.dir);
1876 
1877         err = v9fs_co_readdir(pdu, fidp, &dent);
1878         if (err || !dent) {
1879             break;
1880         }
1881         v9fs_string_init(&name);
1882         v9fs_string_sprintf(&name, "%s", dent->d_name);
1883         if ((count + v9fs_readdir_data_size(&name)) > max_count) {
1884             v9fs_readdir_unlock(&fidp->fs.dir);
1885 
1886             /* Ran out of buffer. Set dir back to old position and return */
1887             v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
1888             v9fs_string_free(&name);
1889             return count;
1890         }
1891         /*
1892          * Fill up just the path field of qid because the client uses
1893          * only that. To fill the entire qid structure we will have
1894          * to stat each dirent found, which is expensive
1895          */
1896         size = MIN(sizeof(dent->d_ino), sizeof(qid.path));
1897         memcpy(&qid.path, &dent->d_ino, size);
1898         /* Fill the other fields with dummy values */
1899         qid.type = 0;
1900         qid.version = 0;
1901 
1902         /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
1903         len = pdu_marshal(pdu, 11 + count, "Qqbs",
1904                           &qid, dent->d_off,
1905                           dent->d_type, &name);
1906 
1907         v9fs_readdir_unlock(&fidp->fs.dir);
1908 
1909         if (len < 0) {
1910             v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
1911             v9fs_string_free(&name);
1912             return len;
1913         }
1914         count += len;
1915         v9fs_string_free(&name);
1916         saved_dir_pos = dent->d_off;
1917     }
1918 
1919     v9fs_readdir_unlock(&fidp->fs.dir);
1920 
1921     if (err < 0) {
1922         return err;
1923     }
1924     return count;
1925 }
1926 
1927 static void coroutine_fn v9fs_readdir(void *opaque)
1928 {
1929     int32_t fid;
1930     V9fsFidState *fidp;
1931     ssize_t retval = 0;
1932     size_t offset = 7;
1933     uint64_t initial_offset;
1934     int32_t count;
1935     uint32_t max_count;
1936     V9fsPDU *pdu = opaque;
1937 
1938     retval = pdu_unmarshal(pdu, offset, "dqd", &fid,
1939                            &initial_offset, &max_count);
1940     if (retval < 0) {
1941         goto out_nofid;
1942     }
1943     trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
1944 
1945     fidp = get_fid(pdu, fid);
1946     if (fidp == NULL) {
1947         retval = -EINVAL;
1948         goto out_nofid;
1949     }
1950     if (!fidp->fs.dir.stream) {
1951         retval = -EINVAL;
1952         goto out;
1953     }
1954     if (initial_offset == 0) {
1955         v9fs_co_rewinddir(pdu, fidp);
1956     } else {
1957         v9fs_co_seekdir(pdu, fidp, initial_offset);
1958     }
1959     count = v9fs_do_readdir(pdu, fidp, max_count);
1960     if (count < 0) {
1961         retval = count;
1962         goto out;
1963     }
1964     retval = pdu_marshal(pdu, offset, "d", count);
1965     if (retval < 0) {
1966         goto out;
1967     }
1968     retval += count + offset;
1969     trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval);
1970 out:
1971     put_fid(pdu, fidp);
1972 out_nofid:
1973     pdu_complete(pdu, retval);
1974 }
1975 
1976 static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
1977                             uint64_t off, uint32_t count,
1978                             struct iovec *sg, int cnt)
1979 {
1980     int i, to_copy;
1981     ssize_t err = 0;
1982     int write_count;
1983     int64_t xattr_len;
1984     size_t offset = 7;
1985 
1986 
1987     xattr_len = fidp->fs.xattr.len;
1988     write_count = xattr_len - off;
1989     if (write_count > count) {
1990         write_count = count;
1991     } else if (write_count < 0) {
1992         /*
1993          * write beyond XATTR value len specified in
1994          * xattrcreate
1995          */
1996         err = -ENOSPC;
1997         goto out;
1998     }
1999     err = pdu_marshal(pdu, offset, "d", write_count);
2000     if (err < 0) {
2001         return err;
2002     }
2003     err += offset;
2004     fidp->fs.xattr.copied_len += write_count;
2005     /*
2006      * Now copy the content from sg list
2007      */
2008     for (i = 0; i < cnt; i++) {
2009         if (write_count > sg[i].iov_len) {
2010             to_copy = sg[i].iov_len;
2011         } else {
2012             to_copy = write_count;
2013         }
2014         memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy);
2015         /* updating vs->off since we are not using below */
2016         off += to_copy;
2017         write_count -= to_copy;
2018     }
2019 out:
2020     return err;
2021 }
2022 
2023 static void coroutine_fn v9fs_write(void *opaque)
2024 {
2025     ssize_t err;
2026     int32_t fid;
2027     uint64_t off;
2028     uint32_t count;
2029     int32_t len = 0;
2030     int32_t total = 0;
2031     size_t offset = 7;
2032     V9fsFidState *fidp;
2033     V9fsPDU *pdu = opaque;
2034     V9fsState *s = pdu->s;
2035     QEMUIOVector qiov_full;
2036     QEMUIOVector qiov;
2037 
2038     err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count);
2039     if (err < 0) {
2040         pdu_complete(pdu, err);
2041         return;
2042     }
2043     offset += err;
2044     v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true);
2045     trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov);
2046 
2047     fidp = get_fid(pdu, fid);
2048     if (fidp == NULL) {
2049         err = -EINVAL;
2050         goto out_nofid;
2051     }
2052     if (fidp->fid_type == P9_FID_FILE) {
2053         if (fidp->fs.fd == -1) {
2054             err = -EINVAL;
2055             goto out;
2056         }
2057     } else if (fidp->fid_type == P9_FID_XATTR) {
2058         /*
2059          * setxattr operation
2060          */
2061         err = v9fs_xattr_write(s, pdu, fidp, off, count,
2062                                qiov_full.iov, qiov_full.niov);
2063         goto out;
2064     } else {
2065         err = -EINVAL;
2066         goto out;
2067     }
2068     qemu_iovec_init(&qiov, qiov_full.niov);
2069     do {
2070         qemu_iovec_reset(&qiov);
2071         qemu_iovec_concat(&qiov, &qiov_full, total, qiov_full.size - total);
2072         if (0) {
2073             print_sg(qiov.iov, qiov.niov);
2074         }
2075         /* Loop in case of EINTR */
2076         do {
2077             len = v9fs_co_pwritev(pdu, fidp, qiov.iov, qiov.niov, off);
2078             if (len >= 0) {
2079                 off   += len;
2080                 total += len;
2081             }
2082         } while (len == -EINTR && !pdu->cancelled);
2083         if (len < 0) {
2084             /* IO error return the error */
2085             err = len;
2086             goto out_qiov;
2087         }
2088     } while (total < count && len > 0);
2089 
2090     offset = 7;
2091     err = pdu_marshal(pdu, offset, "d", total);
2092     if (err < 0) {
2093         goto out_qiov;
2094     }
2095     err += offset;
2096     trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
2097 out_qiov:
2098     qemu_iovec_destroy(&qiov);
2099 out:
2100     put_fid(pdu, fidp);
2101 out_nofid:
2102     qemu_iovec_destroy(&qiov_full);
2103     pdu_complete(pdu, err);
2104 }
2105 
2106 static void coroutine_fn v9fs_create(void *opaque)
2107 {
2108     int32_t fid;
2109     int err = 0;
2110     size_t offset = 7;
2111     V9fsFidState *fidp;
2112     V9fsQID qid;
2113     int32_t perm;
2114     int8_t mode;
2115     V9fsPath path;
2116     struct stat stbuf;
2117     V9fsString name;
2118     V9fsString extension;
2119     int iounit;
2120     V9fsPDU *pdu = opaque;
2121 
2122     v9fs_path_init(&path);
2123     v9fs_string_init(&name);
2124     v9fs_string_init(&extension);
2125     err = pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
2126                         &perm, &mode, &extension);
2127     if (err < 0) {
2128         goto out_nofid;
2129     }
2130     trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
2131 
2132     if (name_is_illegal(name.data)) {
2133         err = -ENOENT;
2134         goto out_nofid;
2135     }
2136 
2137     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2138         err = -EEXIST;
2139         goto out_nofid;
2140     }
2141 
2142     fidp = get_fid(pdu, fid);
2143     if (fidp == NULL) {
2144         err = -EINVAL;
2145         goto out_nofid;
2146     }
2147     if (perm & P9_STAT_MODE_DIR) {
2148         err = v9fs_co_mkdir(pdu, fidp, &name, perm & 0777,
2149                             fidp->uid, -1, &stbuf);
2150         if (err < 0) {
2151             goto out;
2152         }
2153         err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2154         if (err < 0) {
2155             goto out;
2156         }
2157         v9fs_path_copy(&fidp->path, &path);
2158         err = v9fs_co_opendir(pdu, fidp);
2159         if (err < 0) {
2160             goto out;
2161         }
2162         fidp->fid_type = P9_FID_DIR;
2163     } else if (perm & P9_STAT_MODE_SYMLINK) {
2164         err = v9fs_co_symlink(pdu, fidp, &name,
2165                               extension.data, -1 , &stbuf);
2166         if (err < 0) {
2167             goto out;
2168         }
2169         err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2170         if (err < 0) {
2171             goto out;
2172         }
2173         v9fs_path_copy(&fidp->path, &path);
2174     } else if (perm & P9_STAT_MODE_LINK) {
2175         int32_t ofid = atoi(extension.data);
2176         V9fsFidState *ofidp = get_fid(pdu, ofid);
2177         if (ofidp == NULL) {
2178             err = -EINVAL;
2179             goto out;
2180         }
2181         err = v9fs_co_link(pdu, ofidp, fidp, &name);
2182         put_fid(pdu, ofidp);
2183         if (err < 0) {
2184             goto out;
2185         }
2186         err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2187         if (err < 0) {
2188             fidp->fid_type = P9_FID_NONE;
2189             goto out;
2190         }
2191         v9fs_path_copy(&fidp->path, &path);
2192         err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
2193         if (err < 0) {
2194             fidp->fid_type = P9_FID_NONE;
2195             goto out;
2196         }
2197     } else if (perm & P9_STAT_MODE_DEVICE) {
2198         char ctype;
2199         uint32_t major, minor;
2200         mode_t nmode = 0;
2201 
2202         if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) {
2203             err = -errno;
2204             goto out;
2205         }
2206 
2207         switch (ctype) {
2208         case 'c':
2209             nmode = S_IFCHR;
2210             break;
2211         case 'b':
2212             nmode = S_IFBLK;
2213             break;
2214         default:
2215             err = -EIO;
2216             goto out;
2217         }
2218 
2219         nmode |= perm & 0777;
2220         err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
2221                             makedev(major, minor), nmode, &stbuf);
2222         if (err < 0) {
2223             goto out;
2224         }
2225         err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2226         if (err < 0) {
2227             goto out;
2228         }
2229         v9fs_path_copy(&fidp->path, &path);
2230     } else if (perm & P9_STAT_MODE_NAMED_PIPE) {
2231         err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
2232                             0, S_IFIFO | (perm & 0777), &stbuf);
2233         if (err < 0) {
2234             goto out;
2235         }
2236         err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2237         if (err < 0) {
2238             goto out;
2239         }
2240         v9fs_path_copy(&fidp->path, &path);
2241     } else if (perm & P9_STAT_MODE_SOCKET) {
2242         err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
2243                             0, S_IFSOCK | (perm & 0777), &stbuf);
2244         if (err < 0) {
2245             goto out;
2246         }
2247         err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2248         if (err < 0) {
2249             goto out;
2250         }
2251         v9fs_path_copy(&fidp->path, &path);
2252     } else {
2253         err = v9fs_co_open2(pdu, fidp, &name, -1,
2254                             omode_to_uflags(mode)|O_CREAT, perm, &stbuf);
2255         if (err < 0) {
2256             goto out;
2257         }
2258         fidp->fid_type = P9_FID_FILE;
2259         fidp->open_flags = omode_to_uflags(mode);
2260         if (fidp->open_flags & O_EXCL) {
2261             /*
2262              * We let the host file system do O_EXCL check
2263              * We should not reclaim such fd
2264              */
2265             fidp->flags |= FID_NON_RECLAIMABLE;
2266         }
2267     }
2268     iounit = get_iounit(pdu, &fidp->path);
2269     stat_to_qid(&stbuf, &qid);
2270     err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
2271     if (err < 0) {
2272         goto out;
2273     }
2274     err += offset;
2275     trace_v9fs_create_return(pdu->tag, pdu->id,
2276                              qid.type, qid.version, qid.path, iounit);
2277 out:
2278     put_fid(pdu, fidp);
2279 out_nofid:
2280    pdu_complete(pdu, err);
2281    v9fs_string_free(&name);
2282    v9fs_string_free(&extension);
2283    v9fs_path_free(&path);
2284 }
2285 
2286 static void coroutine_fn v9fs_symlink(void *opaque)
2287 {
2288     V9fsPDU *pdu = opaque;
2289     V9fsString name;
2290     V9fsString symname;
2291     V9fsFidState *dfidp;
2292     V9fsQID qid;
2293     struct stat stbuf;
2294     int32_t dfid;
2295     int err = 0;
2296     gid_t gid;
2297     size_t offset = 7;
2298 
2299     v9fs_string_init(&name);
2300     v9fs_string_init(&symname);
2301     err = pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
2302     if (err < 0) {
2303         goto out_nofid;
2304     }
2305     trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
2306 
2307     if (name_is_illegal(name.data)) {
2308         err = -ENOENT;
2309         goto out_nofid;
2310     }
2311 
2312     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2313         err = -EEXIST;
2314         goto out_nofid;
2315     }
2316 
2317     dfidp = get_fid(pdu, dfid);
2318     if (dfidp == NULL) {
2319         err = -EINVAL;
2320         goto out_nofid;
2321     }
2322     err = v9fs_co_symlink(pdu, dfidp, &name, symname.data, gid, &stbuf);
2323     if (err < 0) {
2324         goto out;
2325     }
2326     stat_to_qid(&stbuf, &qid);
2327     err =  pdu_marshal(pdu, offset, "Q", &qid);
2328     if (err < 0) {
2329         goto out;
2330     }
2331     err += offset;
2332     trace_v9fs_symlink_return(pdu->tag, pdu->id,
2333                               qid.type, qid.version, qid.path);
2334 out:
2335     put_fid(pdu, dfidp);
2336 out_nofid:
2337     pdu_complete(pdu, err);
2338     v9fs_string_free(&name);
2339     v9fs_string_free(&symname);
2340 }
2341 
2342 static void v9fs_flush(void *opaque)
2343 {
2344     ssize_t err;
2345     int16_t tag;
2346     size_t offset = 7;
2347     V9fsPDU *cancel_pdu;
2348     V9fsPDU *pdu = opaque;
2349     V9fsState *s = pdu->s;
2350 
2351     err = pdu_unmarshal(pdu, offset, "w", &tag);
2352     if (err < 0) {
2353         pdu_complete(pdu, err);
2354         return;
2355     }
2356     trace_v9fs_flush(pdu->tag, pdu->id, tag);
2357 
2358     QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
2359         if (cancel_pdu->tag == tag) {
2360             break;
2361         }
2362     }
2363     if (cancel_pdu) {
2364         cancel_pdu->cancelled = 1;
2365         /*
2366          * Wait for pdu to complete.
2367          */
2368         qemu_co_queue_wait(&cancel_pdu->complete);
2369         cancel_pdu->cancelled = 0;
2370         pdu_free(cancel_pdu);
2371     }
2372     pdu_complete(pdu, 7);
2373 }
2374 
2375 static void coroutine_fn v9fs_link(void *opaque)
2376 {
2377     V9fsPDU *pdu = opaque;
2378     int32_t dfid, oldfid;
2379     V9fsFidState *dfidp, *oldfidp;
2380     V9fsString name;
2381     size_t offset = 7;
2382     int err = 0;
2383 
2384     v9fs_string_init(&name);
2385     err = pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
2386     if (err < 0) {
2387         goto out_nofid;
2388     }
2389     trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
2390 
2391     if (name_is_illegal(name.data)) {
2392         err = -ENOENT;
2393         goto out_nofid;
2394     }
2395 
2396     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2397         err = -EEXIST;
2398         goto out_nofid;
2399     }
2400 
2401     dfidp = get_fid(pdu, dfid);
2402     if (dfidp == NULL) {
2403         err = -ENOENT;
2404         goto out_nofid;
2405     }
2406 
2407     oldfidp = get_fid(pdu, oldfid);
2408     if (oldfidp == NULL) {
2409         err = -ENOENT;
2410         goto out;
2411     }
2412     err = v9fs_co_link(pdu, oldfidp, dfidp, &name);
2413     if (!err) {
2414         err = offset;
2415     }
2416     put_fid(pdu, oldfidp);
2417 out:
2418     put_fid(pdu, dfidp);
2419 out_nofid:
2420     v9fs_string_free(&name);
2421     pdu_complete(pdu, err);
2422 }
2423 
2424 /* Only works with path name based fid */
2425 static void coroutine_fn v9fs_remove(void *opaque)
2426 {
2427     int32_t fid;
2428     int err = 0;
2429     size_t offset = 7;
2430     V9fsFidState *fidp;
2431     V9fsPDU *pdu = opaque;
2432 
2433     err = pdu_unmarshal(pdu, offset, "d", &fid);
2434     if (err < 0) {
2435         goto out_nofid;
2436     }
2437     trace_v9fs_remove(pdu->tag, pdu->id, fid);
2438 
2439     fidp = get_fid(pdu, fid);
2440     if (fidp == NULL) {
2441         err = -EINVAL;
2442         goto out_nofid;
2443     }
2444     /* if fs driver is not path based, return EOPNOTSUPP */
2445     if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
2446         err = -EOPNOTSUPP;
2447         goto out_err;
2448     }
2449     /*
2450      * IF the file is unlinked, we cannot reopen
2451      * the file later. So don't reclaim fd
2452      */
2453     err = v9fs_mark_fids_unreclaim(pdu, &fidp->path);
2454     if (err < 0) {
2455         goto out_err;
2456     }
2457     err = v9fs_co_remove(pdu, &fidp->path);
2458     if (!err) {
2459         err = offset;
2460     }
2461 out_err:
2462     /* For TREMOVE we need to clunk the fid even on failed remove */
2463     clunk_fid(pdu->s, fidp->fid);
2464     put_fid(pdu, fidp);
2465 out_nofid:
2466     pdu_complete(pdu, err);
2467 }
2468 
2469 static void coroutine_fn v9fs_unlinkat(void *opaque)
2470 {
2471     int err = 0;
2472     V9fsString name;
2473     int32_t dfid, flags;
2474     size_t offset = 7;
2475     V9fsPath path;
2476     V9fsFidState *dfidp;
2477     V9fsPDU *pdu = opaque;
2478 
2479     v9fs_string_init(&name);
2480     err = pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
2481     if (err < 0) {
2482         goto out_nofid;
2483     }
2484 
2485     if (name_is_illegal(name.data)) {
2486         err = -ENOENT;
2487         goto out_nofid;
2488     }
2489 
2490     if (!strcmp(".", name.data)) {
2491         err = -EINVAL;
2492         goto out_nofid;
2493     }
2494 
2495     if (!strcmp("..", name.data)) {
2496         err = -ENOTEMPTY;
2497         goto out_nofid;
2498     }
2499 
2500     dfidp = get_fid(pdu, dfid);
2501     if (dfidp == NULL) {
2502         err = -EINVAL;
2503         goto out_nofid;
2504     }
2505     /*
2506      * IF the file is unlinked, we cannot reopen
2507      * the file later. So don't reclaim fd
2508      */
2509     v9fs_path_init(&path);
2510     err = v9fs_co_name_to_path(pdu, &dfidp->path, name.data, &path);
2511     if (err < 0) {
2512         goto out_err;
2513     }
2514     err = v9fs_mark_fids_unreclaim(pdu, &path);
2515     if (err < 0) {
2516         goto out_err;
2517     }
2518     err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, flags);
2519     if (!err) {
2520         err = offset;
2521     }
2522 out_err:
2523     put_fid(pdu, dfidp);
2524     v9fs_path_free(&path);
2525 out_nofid:
2526     pdu_complete(pdu, err);
2527     v9fs_string_free(&name);
2528 }
2529 
2530 
2531 /* Only works with path name based fid */
2532 static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
2533                                              int32_t newdirfid,
2534                                              V9fsString *name)
2535 {
2536     char *end;
2537     int err = 0;
2538     V9fsPath new_path;
2539     V9fsFidState *tfidp;
2540     V9fsState *s = pdu->s;
2541     V9fsFidState *dirfidp = NULL;
2542     char *old_name, *new_name;
2543 
2544     v9fs_path_init(&new_path);
2545     if (newdirfid != -1) {
2546         dirfidp = get_fid(pdu, newdirfid);
2547         if (dirfidp == NULL) {
2548             err = -ENOENT;
2549             goto out_nofid;
2550         }
2551         BUG_ON(dirfidp->fid_type != P9_FID_NONE);
2552         v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path);
2553     } else {
2554         old_name = fidp->path.data;
2555         end = strrchr(old_name, '/');
2556         if (end) {
2557             end++;
2558         } else {
2559             end = old_name;
2560         }
2561         new_name = g_malloc0(end - old_name + name->size + 1);
2562         strncat(new_name, old_name, end - old_name);
2563         strncat(new_name + (end - old_name), name->data, name->size);
2564         v9fs_co_name_to_path(pdu, NULL, new_name, &new_path);
2565         g_free(new_name);
2566     }
2567     err = v9fs_co_rename(pdu, &fidp->path, &new_path);
2568     if (err < 0) {
2569         goto out;
2570     }
2571     /*
2572      * Fixup fid's pointing to the old name to
2573      * start pointing to the new name
2574      */
2575     for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
2576         if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) {
2577             /* replace the name */
2578             v9fs_fix_path(&tfidp->path, &new_path, strlen(fidp->path.data));
2579         }
2580     }
2581 out:
2582     if (dirfidp) {
2583         put_fid(pdu, dirfidp);
2584     }
2585     v9fs_path_free(&new_path);
2586 out_nofid:
2587     return err;
2588 }
2589 
2590 /* Only works with path name based fid */
2591 static void coroutine_fn v9fs_rename(void *opaque)
2592 {
2593     int32_t fid;
2594     ssize_t err = 0;
2595     size_t offset = 7;
2596     V9fsString name;
2597     int32_t newdirfid;
2598     V9fsFidState *fidp;
2599     V9fsPDU *pdu = opaque;
2600     V9fsState *s = pdu->s;
2601 
2602     v9fs_string_init(&name);
2603     err = pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
2604     if (err < 0) {
2605         goto out_nofid;
2606     }
2607 
2608     if (name_is_illegal(name.data)) {
2609         err = -ENOENT;
2610         goto out_nofid;
2611     }
2612 
2613     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2614         err = -EISDIR;
2615         goto out_nofid;
2616     }
2617 
2618     fidp = get_fid(pdu, fid);
2619     if (fidp == NULL) {
2620         err = -ENOENT;
2621         goto out_nofid;
2622     }
2623     BUG_ON(fidp->fid_type != P9_FID_NONE);
2624     /* if fs driver is not path based, return EOPNOTSUPP */
2625     if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
2626         err = -EOPNOTSUPP;
2627         goto out;
2628     }
2629     v9fs_path_write_lock(s);
2630     err = v9fs_complete_rename(pdu, fidp, newdirfid, &name);
2631     v9fs_path_unlock(s);
2632     if (!err) {
2633         err = offset;
2634     }
2635 out:
2636     put_fid(pdu, fidp);
2637 out_nofid:
2638     pdu_complete(pdu, err);
2639     v9fs_string_free(&name);
2640 }
2641 
2642 static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir,
2643                                             V9fsString *old_name,
2644                                             V9fsPath *newdir,
2645                                             V9fsString *new_name)
2646 {
2647     V9fsFidState *tfidp;
2648     V9fsPath oldpath, newpath;
2649     V9fsState *s = pdu->s;
2650 
2651 
2652     v9fs_path_init(&oldpath);
2653     v9fs_path_init(&newpath);
2654     v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath);
2655     v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath);
2656 
2657     /*
2658      * Fixup fid's pointing to the old name to
2659      * start pointing to the new name
2660      */
2661     for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
2662         if (v9fs_path_is_ancestor(&oldpath, &tfidp->path)) {
2663             /* replace the name */
2664             v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data));
2665         }
2666     }
2667     v9fs_path_free(&oldpath);
2668     v9fs_path_free(&newpath);
2669 }
2670 
2671 static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid,
2672                                                V9fsString *old_name,
2673                                                int32_t newdirfid,
2674                                                V9fsString *new_name)
2675 {
2676     int err = 0;
2677     V9fsState *s = pdu->s;
2678     V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL;
2679 
2680     olddirfidp = get_fid(pdu, olddirfid);
2681     if (olddirfidp == NULL) {
2682         err = -ENOENT;
2683         goto out;
2684     }
2685     if (newdirfid != -1) {
2686         newdirfidp = get_fid(pdu, newdirfid);
2687         if (newdirfidp == NULL) {
2688             err = -ENOENT;
2689             goto out;
2690         }
2691     } else {
2692         newdirfidp = get_fid(pdu, olddirfid);
2693     }
2694 
2695     err = v9fs_co_renameat(pdu, &olddirfidp->path, old_name,
2696                            &newdirfidp->path, new_name);
2697     if (err < 0) {
2698         goto out;
2699     }
2700     if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
2701         /* Only for path based fid  we need to do the below fixup */
2702         v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name,
2703                            &newdirfidp->path, new_name);
2704     }
2705 out:
2706     if (olddirfidp) {
2707         put_fid(pdu, olddirfidp);
2708     }
2709     if (newdirfidp) {
2710         put_fid(pdu, newdirfidp);
2711     }
2712     return err;
2713 }
2714 
2715 static void coroutine_fn v9fs_renameat(void *opaque)
2716 {
2717     ssize_t err = 0;
2718     size_t offset = 7;
2719     V9fsPDU *pdu = opaque;
2720     V9fsState *s = pdu->s;
2721     int32_t olddirfid, newdirfid;
2722     V9fsString old_name, new_name;
2723 
2724     v9fs_string_init(&old_name);
2725     v9fs_string_init(&new_name);
2726     err = pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
2727                         &old_name, &newdirfid, &new_name);
2728     if (err < 0) {
2729         goto out_err;
2730     }
2731 
2732     if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) {
2733         err = -ENOENT;
2734         goto out_err;
2735     }
2736 
2737     if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) ||
2738         !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) {
2739         err = -EISDIR;
2740         goto out_err;
2741     }
2742 
2743     v9fs_path_write_lock(s);
2744     err = v9fs_complete_renameat(pdu, olddirfid,
2745                                  &old_name, newdirfid, &new_name);
2746     v9fs_path_unlock(s);
2747     if (!err) {
2748         err = offset;
2749     }
2750 
2751 out_err:
2752     pdu_complete(pdu, err);
2753     v9fs_string_free(&old_name);
2754     v9fs_string_free(&new_name);
2755 }
2756 
2757 static void coroutine_fn v9fs_wstat(void *opaque)
2758 {
2759     int32_t fid;
2760     int err = 0;
2761     int16_t unused;
2762     V9fsStat v9stat;
2763     size_t offset = 7;
2764     struct stat stbuf;
2765     V9fsFidState *fidp;
2766     V9fsPDU *pdu = opaque;
2767 
2768     v9fs_stat_init(&v9stat);
2769     err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
2770     if (err < 0) {
2771         goto out_nofid;
2772     }
2773     trace_v9fs_wstat(pdu->tag, pdu->id, fid,
2774                      v9stat.mode, v9stat.atime, v9stat.mtime);
2775 
2776     fidp = get_fid(pdu, fid);
2777     if (fidp == NULL) {
2778         err = -EINVAL;
2779         goto out_nofid;
2780     }
2781     /* do we need to sync the file? */
2782     if (donttouch_stat(&v9stat)) {
2783         err = v9fs_co_fsync(pdu, fidp, 0);
2784         goto out;
2785     }
2786     if (v9stat.mode != -1) {
2787         uint32_t v9_mode;
2788         err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
2789         if (err < 0) {
2790             goto out;
2791         }
2792         v9_mode = stat_to_v9mode(&stbuf);
2793         if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
2794             (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
2795             /* Attempting to change the type */
2796             err = -EIO;
2797             goto out;
2798         }
2799         err = v9fs_co_chmod(pdu, &fidp->path,
2800                             v9mode_to_mode(v9stat.mode,
2801                                            &v9stat.extension));
2802         if (err < 0) {
2803             goto out;
2804         }
2805     }
2806     if (v9stat.mtime != -1 || v9stat.atime != -1) {
2807         struct timespec times[2];
2808         if (v9stat.atime != -1) {
2809             times[0].tv_sec = v9stat.atime;
2810             times[0].tv_nsec = 0;
2811         } else {
2812             times[0].tv_nsec = UTIME_OMIT;
2813         }
2814         if (v9stat.mtime != -1) {
2815             times[1].tv_sec = v9stat.mtime;
2816             times[1].tv_nsec = 0;
2817         } else {
2818             times[1].tv_nsec = UTIME_OMIT;
2819         }
2820         err = v9fs_co_utimensat(pdu, &fidp->path, times);
2821         if (err < 0) {
2822             goto out;
2823         }
2824     }
2825     if (v9stat.n_gid != -1 || v9stat.n_uid != -1) {
2826         err = v9fs_co_chown(pdu, &fidp->path, v9stat.n_uid, v9stat.n_gid);
2827         if (err < 0) {
2828             goto out;
2829         }
2830     }
2831     if (v9stat.name.size != 0) {
2832         err = v9fs_complete_rename(pdu, fidp, -1, &v9stat.name);
2833         if (err < 0) {
2834             goto out;
2835         }
2836     }
2837     if (v9stat.length != -1) {
2838         err = v9fs_co_truncate(pdu, &fidp->path, v9stat.length);
2839         if (err < 0) {
2840             goto out;
2841         }
2842     }
2843     err = offset;
2844 out:
2845     put_fid(pdu, fidp);
2846 out_nofid:
2847     v9fs_stat_free(&v9stat);
2848     pdu_complete(pdu, err);
2849 }
2850 
2851 static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf)
2852 {
2853     uint32_t f_type;
2854     uint32_t f_bsize;
2855     uint64_t f_blocks;
2856     uint64_t f_bfree;
2857     uint64_t f_bavail;
2858     uint64_t f_files;
2859     uint64_t f_ffree;
2860     uint64_t fsid_val;
2861     uint32_t f_namelen;
2862     size_t offset = 7;
2863     int32_t bsize_factor;
2864 
2865     /*
2866      * compute bsize factor based on host file system block size
2867      * and client msize
2868      */
2869     bsize_factor = (s->msize - P9_IOHDRSZ)/stbuf->f_bsize;
2870     if (!bsize_factor) {
2871         bsize_factor = 1;
2872     }
2873     f_type  = stbuf->f_type;
2874     f_bsize = stbuf->f_bsize;
2875     f_bsize *= bsize_factor;
2876     /*
2877      * f_bsize is adjusted(multiplied) by bsize factor, so we need to
2878      * adjust(divide) the number of blocks, free blocks and available
2879      * blocks by bsize factor
2880      */
2881     f_blocks = stbuf->f_blocks/bsize_factor;
2882     f_bfree  = stbuf->f_bfree/bsize_factor;
2883     f_bavail = stbuf->f_bavail/bsize_factor;
2884     f_files  = stbuf->f_files;
2885     f_ffree  = stbuf->f_ffree;
2886     fsid_val = (unsigned int) stbuf->f_fsid.__val[0] |
2887                (unsigned long long)stbuf->f_fsid.__val[1] << 32;
2888     f_namelen = stbuf->f_namelen;
2889 
2890     return pdu_marshal(pdu, offset, "ddqqqqqqd",
2891                        f_type, f_bsize, f_blocks, f_bfree,
2892                        f_bavail, f_files, f_ffree,
2893                        fsid_val, f_namelen);
2894 }
2895 
2896 static void coroutine_fn v9fs_statfs(void *opaque)
2897 {
2898     int32_t fid;
2899     ssize_t retval = 0;
2900     size_t offset = 7;
2901     V9fsFidState *fidp;
2902     struct statfs stbuf;
2903     V9fsPDU *pdu = opaque;
2904     V9fsState *s = pdu->s;
2905 
2906     retval = pdu_unmarshal(pdu, offset, "d", &fid);
2907     if (retval < 0) {
2908         goto out_nofid;
2909     }
2910     fidp = get_fid(pdu, fid);
2911     if (fidp == NULL) {
2912         retval = -ENOENT;
2913         goto out_nofid;
2914     }
2915     retval = v9fs_co_statfs(pdu, &fidp->path, &stbuf);
2916     if (retval < 0) {
2917         goto out;
2918     }
2919     retval = v9fs_fill_statfs(s, pdu, &stbuf);
2920     if (retval < 0) {
2921         goto out;
2922     }
2923     retval += offset;
2924 out:
2925     put_fid(pdu, fidp);
2926 out_nofid:
2927     pdu_complete(pdu, retval);
2928 }
2929 
2930 static void coroutine_fn v9fs_mknod(void *opaque)
2931 {
2932 
2933     int mode;
2934     gid_t gid;
2935     int32_t fid;
2936     V9fsQID qid;
2937     int err = 0;
2938     int major, minor;
2939     size_t offset = 7;
2940     V9fsString name;
2941     struct stat stbuf;
2942     V9fsFidState *fidp;
2943     V9fsPDU *pdu = opaque;
2944 
2945     v9fs_string_init(&name);
2946     err = pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
2947                         &major, &minor, &gid);
2948     if (err < 0) {
2949         goto out_nofid;
2950     }
2951     trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
2952 
2953     if (name_is_illegal(name.data)) {
2954         err = -ENOENT;
2955         goto out_nofid;
2956     }
2957 
2958     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2959         err = -EEXIST;
2960         goto out_nofid;
2961     }
2962 
2963     fidp = get_fid(pdu, fid);
2964     if (fidp == NULL) {
2965         err = -ENOENT;
2966         goto out_nofid;
2967     }
2968     err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, gid,
2969                         makedev(major, minor), mode, &stbuf);
2970     if (err < 0) {
2971         goto out;
2972     }
2973     stat_to_qid(&stbuf, &qid);
2974     err = pdu_marshal(pdu, offset, "Q", &qid);
2975     if (err < 0) {
2976         goto out;
2977     }
2978     err += offset;
2979     trace_v9fs_mknod_return(pdu->tag, pdu->id,
2980                             qid.type, qid.version, qid.path);
2981 out:
2982     put_fid(pdu, fidp);
2983 out_nofid:
2984     pdu_complete(pdu, err);
2985     v9fs_string_free(&name);
2986 }
2987 
2988 /*
2989  * Implement posix byte range locking code
2990  * Server side handling of locking code is very simple, because 9p server in
2991  * QEMU can handle only one client. And most of the lock handling
2992  * (like conflict, merging) etc is done by the VFS layer itself, so no need to
2993  * do any thing in * qemu 9p server side lock code path.
2994  * So when a TLOCK request comes, always return success
2995  */
2996 static void coroutine_fn v9fs_lock(void *opaque)
2997 {
2998     int8_t status;
2999     V9fsFlock flock;
3000     size_t offset = 7;
3001     struct stat stbuf;
3002     V9fsFidState *fidp;
3003     int32_t fid, err = 0;
3004     V9fsPDU *pdu = opaque;
3005 
3006     status = P9_LOCK_ERROR;
3007     v9fs_string_init(&flock.client_id);
3008     err = pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock.type,
3009                         &flock.flags, &flock.start, &flock.length,
3010                         &flock.proc_id, &flock.client_id);
3011     if (err < 0) {
3012         goto out_nofid;
3013     }
3014     trace_v9fs_lock(pdu->tag, pdu->id, fid,
3015                     flock.type, flock.start, flock.length);
3016 
3017 
3018     /* We support only block flag now (that too ignored currently) */
3019     if (flock.flags & ~P9_LOCK_FLAGS_BLOCK) {
3020         err = -EINVAL;
3021         goto out_nofid;
3022     }
3023     fidp = get_fid(pdu, fid);
3024     if (fidp == NULL) {
3025         err = -ENOENT;
3026         goto out_nofid;
3027     }
3028     err = v9fs_co_fstat(pdu, fidp, &stbuf);
3029     if (err < 0) {
3030         goto out;
3031     }
3032     status = P9_LOCK_SUCCESS;
3033 out:
3034     put_fid(pdu, fidp);
3035 out_nofid:
3036     err = pdu_marshal(pdu, offset, "b", status);
3037     if (err > 0) {
3038         err += offset;
3039     }
3040     trace_v9fs_lock_return(pdu->tag, pdu->id, status);
3041     pdu_complete(pdu, err);
3042     v9fs_string_free(&flock.client_id);
3043 }
3044 
3045 /*
3046  * When a TGETLOCK request comes, always return success because all lock
3047  * handling is done by client's VFS layer.
3048  */
3049 static void coroutine_fn v9fs_getlock(void *opaque)
3050 {
3051     size_t offset = 7;
3052     struct stat stbuf;
3053     V9fsFidState *fidp;
3054     V9fsGetlock glock;
3055     int32_t fid, err = 0;
3056     V9fsPDU *pdu = opaque;
3057 
3058     v9fs_string_init(&glock.client_id);
3059     err = pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock.type,
3060                         &glock.start, &glock.length, &glock.proc_id,
3061                         &glock.client_id);
3062     if (err < 0) {
3063         goto out_nofid;
3064     }
3065     trace_v9fs_getlock(pdu->tag, pdu->id, fid,
3066                        glock.type, glock.start, glock.length);
3067 
3068     fidp = get_fid(pdu, fid);
3069     if (fidp == NULL) {
3070         err = -ENOENT;
3071         goto out_nofid;
3072     }
3073     err = v9fs_co_fstat(pdu, fidp, &stbuf);
3074     if (err < 0) {
3075         goto out;
3076     }
3077     glock.type = P9_LOCK_TYPE_UNLCK;
3078     err = pdu_marshal(pdu, offset, "bqqds", glock.type,
3079                           glock.start, glock.length, glock.proc_id,
3080                           &glock.client_id);
3081     if (err < 0) {
3082         goto out;
3083     }
3084     err += offset;
3085     trace_v9fs_getlock_return(pdu->tag, pdu->id, glock.type, glock.start,
3086                               glock.length, glock.proc_id);
3087 out:
3088     put_fid(pdu, fidp);
3089 out_nofid:
3090     pdu_complete(pdu, err);
3091     v9fs_string_free(&glock.client_id);
3092 }
3093 
3094 static void coroutine_fn v9fs_mkdir(void *opaque)
3095 {
3096     V9fsPDU *pdu = opaque;
3097     size_t offset = 7;
3098     int32_t fid;
3099     struct stat stbuf;
3100     V9fsQID qid;
3101     V9fsString name;
3102     V9fsFidState *fidp;
3103     gid_t gid;
3104     int mode;
3105     int err = 0;
3106 
3107     v9fs_string_init(&name);
3108     err = pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
3109     if (err < 0) {
3110         goto out_nofid;
3111     }
3112     trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
3113 
3114     if (name_is_illegal(name.data)) {
3115         err = -ENOENT;
3116         goto out_nofid;
3117     }
3118 
3119     if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
3120         err = -EEXIST;
3121         goto out_nofid;
3122     }
3123 
3124     fidp = get_fid(pdu, fid);
3125     if (fidp == NULL) {
3126         err = -ENOENT;
3127         goto out_nofid;
3128     }
3129     err = v9fs_co_mkdir(pdu, fidp, &name, mode, fidp->uid, gid, &stbuf);
3130     if (err < 0) {
3131         goto out;
3132     }
3133     stat_to_qid(&stbuf, &qid);
3134     err = pdu_marshal(pdu, offset, "Q", &qid);
3135     if (err < 0) {
3136         goto out;
3137     }
3138     err += offset;
3139     trace_v9fs_mkdir_return(pdu->tag, pdu->id,
3140                             qid.type, qid.version, qid.path, err);
3141 out:
3142     put_fid(pdu, fidp);
3143 out_nofid:
3144     pdu_complete(pdu, err);
3145     v9fs_string_free(&name);
3146 }
3147 
3148 static void coroutine_fn v9fs_xattrwalk(void *opaque)
3149 {
3150     int64_t size;
3151     V9fsString name;
3152     ssize_t err = 0;
3153     size_t offset = 7;
3154     int32_t fid, newfid;
3155     V9fsFidState *file_fidp;
3156     V9fsFidState *xattr_fidp = NULL;
3157     V9fsPDU *pdu = opaque;
3158     V9fsState *s = pdu->s;
3159 
3160     v9fs_string_init(&name);
3161     err = pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
3162     if (err < 0) {
3163         goto out_nofid;
3164     }
3165     trace_v9fs_xattrwalk(pdu->tag, pdu->id, fid, newfid, name.data);
3166 
3167     file_fidp = get_fid(pdu, fid);
3168     if (file_fidp == NULL) {
3169         err = -ENOENT;
3170         goto out_nofid;
3171     }
3172     xattr_fidp = alloc_fid(s, newfid);
3173     if (xattr_fidp == NULL) {
3174         err = -EINVAL;
3175         goto out;
3176     }
3177     v9fs_path_copy(&xattr_fidp->path, &file_fidp->path);
3178     if (!v9fs_string_size(&name)) {
3179         /*
3180          * listxattr request. Get the size first
3181          */
3182         size = v9fs_co_llistxattr(pdu, &xattr_fidp->path, NULL, 0);
3183         if (size < 0) {
3184             err = size;
3185             clunk_fid(s, xattr_fidp->fid);
3186             goto out;
3187         }
3188         /*
3189          * Read the xattr value
3190          */
3191         xattr_fidp->fs.xattr.len = size;
3192         xattr_fidp->fid_type = P9_FID_XATTR;
3193         xattr_fidp->fs.xattr.copied_len = -1;
3194         if (size) {
3195             xattr_fidp->fs.xattr.value = g_malloc(size);
3196             err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
3197                                      xattr_fidp->fs.xattr.value,
3198                                      xattr_fidp->fs.xattr.len);
3199             if (err < 0) {
3200                 clunk_fid(s, xattr_fidp->fid);
3201                 goto out;
3202             }
3203         }
3204         err = pdu_marshal(pdu, offset, "q", size);
3205         if (err < 0) {
3206             goto out;
3207         }
3208         err += offset;
3209     } else {
3210         /*
3211          * specific xattr fid. We check for xattr
3212          * presence also collect the xattr size
3213          */
3214         size = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
3215                                  &name, NULL, 0);
3216         if (size < 0) {
3217             err = size;
3218             clunk_fid(s, xattr_fidp->fid);
3219             goto out;
3220         }
3221         /*
3222          * Read the xattr value
3223          */
3224         xattr_fidp->fs.xattr.len = size;
3225         xattr_fidp->fid_type = P9_FID_XATTR;
3226         xattr_fidp->fs.xattr.copied_len = -1;
3227         if (size) {
3228             xattr_fidp->fs.xattr.value = g_malloc(size);
3229             err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
3230                                     &name, xattr_fidp->fs.xattr.value,
3231                                     xattr_fidp->fs.xattr.len);
3232             if (err < 0) {
3233                 clunk_fid(s, xattr_fidp->fid);
3234                 goto out;
3235             }
3236         }
3237         err = pdu_marshal(pdu, offset, "q", size);
3238         if (err < 0) {
3239             goto out;
3240         }
3241         err += offset;
3242     }
3243     trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size);
3244 out:
3245     put_fid(pdu, file_fidp);
3246     if (xattr_fidp) {
3247         put_fid(pdu, xattr_fidp);
3248     }
3249 out_nofid:
3250     pdu_complete(pdu, err);
3251     v9fs_string_free(&name);
3252 }
3253 
3254 static void coroutine_fn v9fs_xattrcreate(void *opaque)
3255 {
3256     int flags;
3257     int32_t fid;
3258     int64_t size;
3259     ssize_t err = 0;
3260     V9fsString name;
3261     size_t offset = 7;
3262     V9fsFidState *file_fidp;
3263     V9fsFidState *xattr_fidp;
3264     V9fsPDU *pdu = opaque;
3265 
3266     v9fs_string_init(&name);
3267     err = pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags);
3268     if (err < 0) {
3269         goto out_nofid;
3270     }
3271     trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
3272 
3273     file_fidp = get_fid(pdu, fid);
3274     if (file_fidp == NULL) {
3275         err = -EINVAL;
3276         goto out_nofid;
3277     }
3278     /* Make the file fid point to xattr */
3279     xattr_fidp = file_fidp;
3280     xattr_fidp->fid_type = P9_FID_XATTR;
3281     xattr_fidp->fs.xattr.copied_len = 0;
3282     xattr_fidp->fs.xattr.len = size;
3283     xattr_fidp->fs.xattr.flags = flags;
3284     v9fs_string_init(&xattr_fidp->fs.xattr.name);
3285     v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name);
3286     g_free(xattr_fidp->fs.xattr.value);
3287     xattr_fidp->fs.xattr.value = g_malloc0(size);
3288     err = offset;
3289     put_fid(pdu, file_fidp);
3290 out_nofid:
3291     pdu_complete(pdu, err);
3292     v9fs_string_free(&name);
3293 }
3294 
3295 static void coroutine_fn v9fs_readlink(void *opaque)
3296 {
3297     V9fsPDU *pdu = opaque;
3298     size_t offset = 7;
3299     V9fsString target;
3300     int32_t fid;
3301     int err = 0;
3302     V9fsFidState *fidp;
3303 
3304     err = pdu_unmarshal(pdu, offset, "d", &fid);
3305     if (err < 0) {
3306         goto out_nofid;
3307     }
3308     trace_v9fs_readlink(pdu->tag, pdu->id, fid);
3309     fidp = get_fid(pdu, fid);
3310     if (fidp == NULL) {
3311         err = -ENOENT;
3312         goto out_nofid;
3313     }
3314 
3315     v9fs_string_init(&target);
3316     err = v9fs_co_readlink(pdu, &fidp->path, &target);
3317     if (err < 0) {
3318         goto out;
3319     }
3320     err = pdu_marshal(pdu, offset, "s", &target);
3321     if (err < 0) {
3322         v9fs_string_free(&target);
3323         goto out;
3324     }
3325     err += offset;
3326     trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data);
3327     v9fs_string_free(&target);
3328 out:
3329     put_fid(pdu, fidp);
3330 out_nofid:
3331     pdu_complete(pdu, err);
3332 }
3333 
3334 static CoroutineEntry *pdu_co_handlers[] = {
3335     [P9_TREADDIR] = v9fs_readdir,
3336     [P9_TSTATFS] = v9fs_statfs,
3337     [P9_TGETATTR] = v9fs_getattr,
3338     [P9_TSETATTR] = v9fs_setattr,
3339     [P9_TXATTRWALK] = v9fs_xattrwalk,
3340     [P9_TXATTRCREATE] = v9fs_xattrcreate,
3341     [P9_TMKNOD] = v9fs_mknod,
3342     [P9_TRENAME] = v9fs_rename,
3343     [P9_TLOCK] = v9fs_lock,
3344     [P9_TGETLOCK] = v9fs_getlock,
3345     [P9_TRENAMEAT] = v9fs_renameat,
3346     [P9_TREADLINK] = v9fs_readlink,
3347     [P9_TUNLINKAT] = v9fs_unlinkat,
3348     [P9_TMKDIR] = v9fs_mkdir,
3349     [P9_TVERSION] = v9fs_version,
3350     [P9_TLOPEN] = v9fs_open,
3351     [P9_TATTACH] = v9fs_attach,
3352     [P9_TSTAT] = v9fs_stat,
3353     [P9_TWALK] = v9fs_walk,
3354     [P9_TCLUNK] = v9fs_clunk,
3355     [P9_TFSYNC] = v9fs_fsync,
3356     [P9_TOPEN] = v9fs_open,
3357     [P9_TREAD] = v9fs_read,
3358 #if 0
3359     [P9_TAUTH] = v9fs_auth,
3360 #endif
3361     [P9_TFLUSH] = v9fs_flush,
3362     [P9_TLINK] = v9fs_link,
3363     [P9_TSYMLINK] = v9fs_symlink,
3364     [P9_TCREATE] = v9fs_create,
3365     [P9_TLCREATE] = v9fs_lcreate,
3366     [P9_TWRITE] = v9fs_write,
3367     [P9_TWSTAT] = v9fs_wstat,
3368     [P9_TREMOVE] = v9fs_remove,
3369 };
3370 
3371 static void coroutine_fn v9fs_op_not_supp(void *opaque)
3372 {
3373     V9fsPDU *pdu = opaque;
3374     pdu_complete(pdu, -EOPNOTSUPP);
3375 }
3376 
3377 static void coroutine_fn v9fs_fs_ro(void *opaque)
3378 {
3379     V9fsPDU *pdu = opaque;
3380     pdu_complete(pdu, -EROFS);
3381 }
3382 
3383 static inline bool is_read_only_op(V9fsPDU *pdu)
3384 {
3385     switch (pdu->id) {
3386     case P9_TREADDIR:
3387     case P9_TSTATFS:
3388     case P9_TGETATTR:
3389     case P9_TXATTRWALK:
3390     case P9_TLOCK:
3391     case P9_TGETLOCK:
3392     case P9_TREADLINK:
3393     case P9_TVERSION:
3394     case P9_TLOPEN:
3395     case P9_TATTACH:
3396     case P9_TSTAT:
3397     case P9_TWALK:
3398     case P9_TCLUNK:
3399     case P9_TFSYNC:
3400     case P9_TOPEN:
3401     case P9_TREAD:
3402     case P9_TAUTH:
3403     case P9_TFLUSH:
3404         return 1;
3405     default:
3406         return 0;
3407     }
3408 }
3409 
3410 void pdu_submit(V9fsPDU *pdu)
3411 {
3412     Coroutine *co;
3413     CoroutineEntry *handler;
3414     V9fsState *s = pdu->s;
3415 
3416     if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
3417         (pdu_co_handlers[pdu->id] == NULL)) {
3418         handler = v9fs_op_not_supp;
3419     } else {
3420         handler = pdu_co_handlers[pdu->id];
3421     }
3422 
3423     if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
3424         handler = v9fs_fs_ro;
3425     }
3426     co = qemu_coroutine_create(handler, pdu);
3427     qemu_coroutine_enter(co);
3428 }
3429 
3430 /* Returns 0 on success, 1 on failure. */
3431 int v9fs_device_realize_common(V9fsState *s, Error **errp)
3432 {
3433     V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
3434     int i, len;
3435     struct stat stat;
3436     FsDriverEntry *fse;
3437     V9fsPath path;
3438     int rc = 1;
3439 
3440     /* initialize pdu allocator */
3441     QLIST_INIT(&s->free_list);
3442     QLIST_INIT(&s->active_list);
3443     for (i = 0; i < (MAX_REQ - 1); i++) {
3444         QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next);
3445         v->pdus[i].s = s;
3446         v->pdus[i].idx = i;
3447     }
3448 
3449     v9fs_path_init(&path);
3450 
3451     fse = get_fsdev_fsentry(s->fsconf.fsdev_id);
3452 
3453     if (!fse) {
3454         /* We don't have a fsdev identified by fsdev_id */
3455         error_setg(errp, "9pfs device couldn't find fsdev with the "
3456                    "id = %s",
3457                    s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
3458         goto out;
3459     }
3460 
3461     if (!s->fsconf.tag) {
3462         /* we haven't specified a mount_tag */
3463         error_setg(errp, "fsdev with id %s needs mount_tag arguments",
3464                    s->fsconf.fsdev_id);
3465         goto out;
3466     }
3467 
3468     s->ctx.export_flags = fse->export_flags;
3469     s->ctx.fs_root = g_strdup(fse->path);
3470     s->ctx.exops.get_st_gen = NULL;
3471     len = strlen(s->fsconf.tag);
3472     if (len > MAX_TAG_LEN - 1) {
3473         error_setg(errp, "mount tag '%s' (%d bytes) is longer than "
3474                    "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
3475         goto out;
3476     }
3477 
3478     s->tag = g_strdup(s->fsconf.tag);
3479     s->ctx.uid = -1;
3480 
3481     s->ops = fse->ops;
3482 
3483     s->fid_list = NULL;
3484     qemu_co_rwlock_init(&s->rename_lock);
3485 
3486     if (s->ops->init(&s->ctx) < 0) {
3487         error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s"
3488                    " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root);
3489         goto out;
3490     }
3491 
3492     /*
3493      * Check details of export path, We need to use fs driver
3494      * call back to do that. Since we are in the init path, we don't
3495      * use co-routines here.
3496      */
3497     if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
3498         error_setg(errp,
3499                    "error in converting name to path %s", strerror(errno));
3500         goto out;
3501     }
3502     if (s->ops->lstat(&s->ctx, &path, &stat)) {
3503         error_setg(errp, "share path %s does not exist", fse->path);
3504         goto out;
3505     } else if (!S_ISDIR(stat.st_mode)) {
3506         error_setg(errp, "share path %s is not a directory", fse->path);
3507         goto out;
3508     }
3509     v9fs_path_free(&path);
3510 
3511     rc = 0;
3512 out:
3513     if (rc) {
3514         g_free(s->ctx.fs_root);
3515         g_free(s->tag);
3516         v9fs_path_free(&path);
3517     }
3518     return rc;
3519 }
3520 
3521 void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
3522 {
3523     g_free(s->ctx.fs_root);
3524     g_free(s->tag);
3525 }
3526 
3527 typedef struct VirtfsCoResetData {
3528     V9fsPDU pdu;
3529     bool done;
3530 } VirtfsCoResetData;
3531 
3532 static void coroutine_fn virtfs_co_reset(void *opaque)
3533 {
3534     VirtfsCoResetData *data = opaque;
3535 
3536     virtfs_reset(&data->pdu);
3537     data->done = true;
3538 }
3539 
3540 void v9fs_reset(V9fsState *s)
3541 {
3542     VirtfsCoResetData data = { .pdu = { .s = s }, .done = false };
3543     Coroutine *co;
3544 
3545     while (!QLIST_EMPTY(&s->active_list)) {
3546         aio_poll(qemu_get_aio_context(), true);
3547     }
3548 
3549     co = qemu_coroutine_create(virtfs_co_reset, &data);
3550     qemu_coroutine_enter(co);
3551 
3552     while (!data.done) {
3553         aio_poll(qemu_get_aio_context(), true);
3554     }
3555 }
3556 
3557 static void __attribute__((__constructor__)) v9fs_set_fd_limit(void)
3558 {
3559     struct rlimit rlim;
3560     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
3561         error_report("Failed to get the resource limit");
3562         exit(1);
3563     }
3564     open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
3565     open_fd_rc = rlim.rlim_cur/2;
3566 }
3567