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