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