]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/kvm/virtio/9p.c
Merge remote-tracking branch 'signal/for-next'
[karo-tx-linux.git] / tools / kvm / virtio / 9p.c
1 #include "kvm/virtio-pci-dev.h"
2 #include "kvm/ioport.h"
3 #include "kvm/util.h"
4 #include "kvm/threadpool.h"
5 #include "kvm/irq.h"
6 #include "kvm/virtio-9p.h"
7 #include "kvm/guest_compat.h"
8 #include "kvm/builtin-setup.h"
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <sys/vfs.h>
18
19 #include <linux/virtio_ring.h>
20 #include <linux/virtio_9p.h>
21 #include <net/9p/9p.h>
22
23 static LIST_HEAD(devs);
24 static int compat_id = -1;
25
26 static int insert_new_fid(struct p9_dev *dev, struct p9_fid *fid);
27 static struct p9_fid *find_or_create_fid(struct p9_dev *dev, u32 fid)
28 {
29         struct rb_node *node = dev->fids.rb_node;
30         struct p9_fid *pfid = NULL;
31
32         while (node) {
33                 struct p9_fid *cur = rb_entry(node, struct p9_fid, node);
34
35                 if (fid < cur->fid) {
36                         node = node->rb_left;
37                 } else if (fid > cur->fid) {
38                         node = node->rb_right;
39                 } else {
40                         return cur;
41                 }
42         }
43
44         pfid = calloc(sizeof(*pfid), 1);
45         if (!pfid)
46                 return NULL;
47
48         pfid->fid = fid;
49         strcpy(pfid->abs_path, dev->root_dir);
50         pfid->path = pfid->abs_path + strlen(dev->root_dir);
51
52         insert_new_fid(dev, pfid);
53
54         return pfid;
55 }
56
57 static int insert_new_fid(struct p9_dev *dev, struct p9_fid *fid)
58 {
59         struct rb_node **node = &(dev->fids.rb_node), *parent = NULL;
60
61         while (*node) {
62                 int result = fid->fid - rb_entry(*node, struct p9_fid, node)->fid;
63
64                 parent = *node;
65                 if (result < 0)
66                         node    = &((*node)->rb_left);
67                 else if (result > 0)
68                         node    = &((*node)->rb_right);
69                 else
70                         return -EEXIST;
71         }
72
73         rb_link_node(&fid->node, parent, node);
74         rb_insert_color(&fid->node, &dev->fids);
75         return 0;
76 }
77
78 static struct p9_fid *get_fid(struct p9_dev *p9dev, int fid)
79 {
80         struct p9_fid *new;
81
82         new = find_or_create_fid(p9dev, fid);
83
84         return new;
85 }
86
87 /* Warning: Immediately use value returned from this function */
88 static const char *rel_to_abs(struct p9_dev *p9dev,
89                               const char *path, char *abs_path)
90 {
91         sprintf(abs_path, "%s/%s", p9dev->root_dir, path);
92
93         return abs_path;
94 }
95
96 static void stat2qid(struct stat *st, struct p9_qid *qid)
97 {
98         *qid = (struct p9_qid) {
99                 .path           = st->st_ino,
100                 .version        = st->st_mtime,
101         };
102
103         if (S_ISDIR(st->st_mode))
104                 qid->type       |= P9_QTDIR;
105 }
106
107 static void close_fid(struct p9_dev *p9dev, u32 fid)
108 {
109         struct p9_fid *pfid = get_fid(p9dev, fid);
110
111         if (pfid->fd > 0)
112                 close(pfid->fd);
113
114         if (pfid->dir)
115                 closedir(pfid->dir);
116
117         rb_erase(&pfid->node, &p9dev->fids);
118         free(pfid);
119 }
120
121 static void virtio_p9_set_reply_header(struct p9_pdu *pdu, u32 size)
122 {
123         u8 cmd;
124         u16 tag;
125
126         pdu->read_offset = sizeof(u32);
127         virtio_p9_pdu_readf(pdu, "bw", &cmd, &tag);
128         pdu->write_offset = 0;
129         /* cmd + 1 is the reply message */
130         virtio_p9_pdu_writef(pdu, "dbw", size, cmd + 1, tag);
131 }
132
133 static u16 virtio_p9_update_iov_cnt(struct iovec iov[], u32 count, int iov_cnt)
134 {
135         int i;
136         u32 total = 0;
137         for (i = 0; (i < iov_cnt) && (total < count); i++) {
138                 if (total + iov[i].iov_len > count) {
139                         /* we don't need this iov fully */
140                         iov[i].iov_len -= ((total + iov[i].iov_len) - count);
141                         i++;
142                         break;
143                 }
144                 total += iov[i].iov_len;
145         }
146         return i;
147 }
148
149 static void virtio_p9_error_reply(struct p9_dev *p9dev,
150                                   struct p9_pdu *pdu, int err, u32 *outlen)
151 {
152         u16 tag;
153
154         pdu->write_offset = VIRTIO_9P_HDR_LEN;
155         virtio_p9_pdu_writef(pdu, "d", err);
156         *outlen = pdu->write_offset;
157
158         /* read the tag from input */
159         pdu->read_offset = sizeof(u32) + sizeof(u8);
160         virtio_p9_pdu_readf(pdu, "w", &tag);
161
162         /* Update the header */
163         pdu->write_offset = 0;
164         virtio_p9_pdu_writef(pdu, "dbw", *outlen, P9_RLERROR, tag);
165 }
166
167 static void virtio_p9_version(struct p9_dev *p9dev,
168                               struct p9_pdu *pdu, u32 *outlen)
169 {
170         u32 msize;
171         char *version;
172         virtio_p9_pdu_readf(pdu, "ds", &msize, &version);
173         /*
174          * reply with the same msize the client sent us
175          * Error out if the request is not for 9P2000.L
176          */
177         if (!strcmp(version, VIRTIO_9P_VERSION_DOTL))
178                 virtio_p9_pdu_writef(pdu, "ds", msize, version);
179         else
180                 virtio_p9_pdu_writef(pdu, "ds", msize, "unknown");
181
182         *outlen = pdu->write_offset;
183         virtio_p9_set_reply_header(pdu, *outlen);
184         free(version);
185         return;
186 }
187
188 static void virtio_p9_clunk(struct p9_dev *p9dev,
189                             struct p9_pdu *pdu, u32 *outlen)
190 {
191         u32 fid;
192
193         virtio_p9_pdu_readf(pdu, "d", &fid);
194         close_fid(p9dev, fid);
195
196         *outlen = pdu->write_offset;
197         virtio_p9_set_reply_header(pdu, *outlen);
198         return;
199 }
200
201 /*
202  * FIXME!! Need to map to protocol independent value. Upstream
203  * 9p also have the same BUG
204  */
205 static int virtio_p9_openflags(int flags)
206 {
207         flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT | O_DIRECT);
208         flags |= O_NOFOLLOW;
209         return flags;
210 }
211
212 static bool is_dir(struct p9_fid *fid)
213 {
214         struct stat st;
215
216         stat(fid->abs_path, &st);
217
218         return S_ISDIR(st.st_mode);
219 }
220
221 static void virtio_p9_open(struct p9_dev *p9dev,
222                            struct p9_pdu *pdu, u32 *outlen)
223 {
224         u32 fid, flags;
225         struct stat st;
226         struct p9_qid qid;
227         struct p9_fid *new_fid;
228
229
230         virtio_p9_pdu_readf(pdu, "dd", &fid, &flags);
231         new_fid = get_fid(p9dev, fid);
232
233         if (lstat(new_fid->abs_path, &st) < 0)
234                 goto err_out;
235
236         stat2qid(&st, &qid);
237
238         if (is_dir(new_fid)) {
239                 new_fid->dir = opendir(new_fid->abs_path);
240                 if (!new_fid->dir)
241                         goto err_out;
242         } else {
243                 new_fid->fd  = open(new_fid->abs_path,
244                                     virtio_p9_openflags(flags));
245                 if (new_fid->fd < 0)
246                         goto err_out;
247         }
248         /* FIXME!! need ot send proper iounit  */
249         virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
250
251         *outlen = pdu->write_offset;
252         virtio_p9_set_reply_header(pdu, *outlen);
253         return;
254 err_out:
255         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
256         return;
257 }
258
259 static void virtio_p9_create(struct p9_dev *p9dev,
260                              struct p9_pdu *pdu, u32 *outlen)
261 {
262         int fd, ret;
263         char *name;
264         struct stat st;
265         struct p9_qid qid;
266         struct p9_fid *dfid;
267         char full_path[PATH_MAX];
268         u32 dfid_val, flags, mode, gid;
269
270         virtio_p9_pdu_readf(pdu, "dsddd", &dfid_val,
271                             &name, &flags, &mode, &gid);
272         dfid = get_fid(p9dev, dfid_val);
273
274         flags = virtio_p9_openflags(flags);
275
276         sprintf(full_path, "%s/%s", dfid->abs_path, name);
277         fd = open(full_path, flags | O_CREAT, mode);
278         if (fd < 0)
279                 goto err_out;
280         dfid->fd = fd;
281
282         if (lstat(full_path, &st) < 0)
283                 goto err_out;
284
285         ret = chmod(full_path, mode & 0777);
286         if (ret < 0)
287                 goto err_out;
288
289         sprintf(dfid->path, "%s/%s", dfid->path, name);
290         stat2qid(&st, &qid);
291         virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
292         *outlen = pdu->write_offset;
293         virtio_p9_set_reply_header(pdu, *outlen);
294         free(name);
295         return;
296 err_out:
297         free(name);
298         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
299         return;
300 }
301
302 static void virtio_p9_mkdir(struct p9_dev *p9dev,
303                             struct p9_pdu *pdu, u32 *outlen)
304 {
305         int ret;
306         char *name;
307         struct stat st;
308         struct p9_qid qid;
309         struct p9_fid *dfid;
310         char full_path[PATH_MAX];
311         u32 dfid_val, mode, gid;
312
313         virtio_p9_pdu_readf(pdu, "dsdd", &dfid_val,
314                             &name, &mode, &gid);
315         dfid = get_fid(p9dev, dfid_val);
316
317         sprintf(full_path, "%s/%s", dfid->abs_path, name);
318         ret = mkdir(full_path, mode);
319         if (ret < 0)
320                 goto err_out;
321
322         if (lstat(full_path, &st) < 0)
323                 goto err_out;
324
325         ret = chmod(full_path, mode & 0777);
326         if (ret < 0)
327                 goto err_out;
328
329         stat2qid(&st, &qid);
330         virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
331         *outlen = pdu->write_offset;
332         virtio_p9_set_reply_header(pdu, *outlen);
333         free(name);
334         return;
335 err_out:
336         free(name);
337         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
338         return;
339 }
340
341 static void virtio_p9_walk(struct p9_dev *p9dev,
342                            struct p9_pdu *pdu, u32 *outlen)
343 {
344         u8 i;
345         u16 nwqid;
346         u16 nwname;
347         struct p9_qid wqid;
348         struct p9_fid *new_fid, *old_fid;
349         u32 fid_val, newfid_val;
350
351
352         virtio_p9_pdu_readf(pdu, "ddw", &fid_val, &newfid_val, &nwname);
353         new_fid = get_fid(p9dev, newfid_val);
354
355         nwqid = 0;
356         if (nwname) {
357                 struct p9_fid *fid = get_fid(p9dev, fid_val);
358
359                 strcpy(new_fid->path, fid->path);
360                 /* skip the space for count */
361                 pdu->write_offset += sizeof(u16);
362                 for (i = 0; i < nwname; i++) {
363                         struct stat st;
364                         char tmp[PATH_MAX] = {0};
365                         char full_path[PATH_MAX];
366                         char *str;
367
368                         virtio_p9_pdu_readf(pdu, "s", &str);
369
370                         /* Format the new path we're 'walk'ing into */
371                         sprintf(tmp, "%s/%s", new_fid->path, str);
372
373                         free(str);
374
375                         if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
376                                 goto err_out;
377
378                         stat2qid(&st, &wqid);
379                         strcpy(new_fid->path, tmp);
380                         new_fid->uid = fid->uid;
381                         nwqid++;
382                         virtio_p9_pdu_writef(pdu, "Q", &wqid);
383                 }
384         } else {
385                 /*
386                  * update write_offset so our outlen get correct value
387                  */
388                 pdu->write_offset += sizeof(u16);
389                 old_fid = get_fid(p9dev, fid_val);
390                 strcpy(new_fid->path, old_fid->path);
391                 new_fid->uid    = old_fid->uid;
392         }
393         *outlen = pdu->write_offset;
394         pdu->write_offset = VIRTIO_9P_HDR_LEN;
395         virtio_p9_pdu_writef(pdu, "d", nwqid);
396         virtio_p9_set_reply_header(pdu, *outlen);
397         return;
398 err_out:
399         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
400         return;
401 }
402
403 static void virtio_p9_attach(struct p9_dev *p9dev,
404                              struct p9_pdu *pdu, u32 *outlen)
405 {
406         char *uname;
407         char *aname;
408         struct stat st;
409         struct p9_qid qid;
410         struct p9_fid *fid;
411         u32 fid_val, afid, uid;
412
413         virtio_p9_pdu_readf(pdu, "ddssd", &fid_val, &afid,
414                             &uname, &aname, &uid);
415
416         free(uname);
417         free(aname);
418
419         if (lstat(p9dev->root_dir, &st) < 0)
420                 goto err_out;
421
422         stat2qid(&st, &qid);
423
424         fid = get_fid(p9dev, fid_val);
425         fid->uid = uid;
426         strcpy(fid->path, "/");
427
428         virtio_p9_pdu_writef(pdu, "Q", &qid);
429         *outlen = pdu->write_offset;
430         virtio_p9_set_reply_header(pdu, *outlen);
431         return;
432 err_out:
433         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
434         return;
435 }
436
437 static void virtio_p9_fill_stat(struct p9_dev *p9dev,
438                                 struct stat *st, struct p9_stat_dotl *statl)
439 {
440         memset(statl, 0, sizeof(*statl));
441         statl->st_mode          = st->st_mode;
442         statl->st_nlink         = st->st_nlink;
443         statl->st_uid           = st->st_uid;
444         statl->st_gid           = st->st_gid;
445         statl->st_rdev          = st->st_rdev;
446         statl->st_size          = st->st_size;
447         statl->st_blksize       = st->st_blksize;
448         statl->st_blocks        = st->st_blocks;
449         statl->st_atime_sec     = st->st_atime;
450         statl->st_atime_nsec    = st->st_atim.tv_nsec;
451         statl->st_mtime_sec     = st->st_mtime;
452         statl->st_mtime_nsec    = st->st_mtim.tv_nsec;
453         statl->st_ctime_sec     = st->st_ctime;
454         statl->st_ctime_nsec    = st->st_ctim.tv_nsec;
455         /* Currently we only support BASIC fields in stat */
456         statl->st_result_mask   = P9_STATS_BASIC;
457         stat2qid(st, &statl->qid);
458 }
459
460 static void virtio_p9_read(struct p9_dev *p9dev,
461                            struct p9_pdu *pdu, u32 *outlen)
462 {
463         u64 offset;
464         u32 fid_val;
465         u16 iov_cnt;
466         void *iov_base;
467         size_t iov_len;
468         u32 count, rcount;
469         struct p9_fid *fid;
470
471
472         rcount = 0;
473         virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
474         fid = get_fid(p9dev, fid_val);
475
476         iov_base = pdu->in_iov[0].iov_base;
477         iov_len  = pdu->in_iov[0].iov_len;
478         iov_cnt  = pdu->in_iov_cnt;
479         pdu->in_iov[0].iov_base += VIRTIO_9P_HDR_LEN + sizeof(u32);
480         pdu->in_iov[0].iov_len -= VIRTIO_9P_HDR_LEN + sizeof(u32);
481         pdu->in_iov_cnt = virtio_p9_update_iov_cnt(pdu->in_iov,
482                                                    count,
483                                                    pdu->in_iov_cnt);
484         rcount = preadv(fid->fd, pdu->in_iov,
485                         pdu->in_iov_cnt, offset);
486         if (rcount > count)
487                 rcount = count;
488         /*
489          * Update the iov_base back, so that rest of
490          * pdu_writef works correctly.
491          */
492         pdu->in_iov[0].iov_base = iov_base;
493         pdu->in_iov[0].iov_len  = iov_len;
494         pdu->in_iov_cnt         = iov_cnt;
495
496         pdu->write_offset = VIRTIO_9P_HDR_LEN;
497         virtio_p9_pdu_writef(pdu, "d", rcount);
498         *outlen = pdu->write_offset + rcount;
499         virtio_p9_set_reply_header(pdu, *outlen);
500         return;
501 }
502
503 static int virtio_p9_dentry_size(struct dirent *dent)
504 {
505         /*
506          * Size of each dirent:
507          * qid(13) + offset(8) + type(1) + name_len(2) + name
508          */
509         return 24 + strlen(dent->d_name);
510 }
511
512 static void virtio_p9_readdir(struct p9_dev *p9dev,
513                               struct p9_pdu *pdu, u32 *outlen)
514 {
515         u32 fid_val;
516         u32 count, rcount;
517         struct stat st;
518         struct p9_fid *fid;
519         struct dirent *dent;
520         char full_path[PATH_MAX];
521         u64 offset, old_offset;
522
523         rcount = 0;
524         virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
525         fid = get_fid(p9dev, fid_val);
526
527         if (!is_dir(fid)) {
528                 errno = EINVAL;
529                 goto err_out;
530         }
531
532         /* Move the offset specified */
533         seekdir(fid->dir, offset);
534
535         old_offset = offset;
536         /* If reading a dir, fill the buffer with p9_stat entries */
537         dent = readdir(fid->dir);
538
539         /* Skip the space for writing count */
540         pdu->write_offset += sizeof(u32);
541         while (dent) {
542                 u32 read;
543                 struct p9_qid qid;
544
545                 if ((rcount + virtio_p9_dentry_size(dent)) > count) {
546                         /* seek to the previous offset and return */
547                         seekdir(fid->dir, old_offset);
548                         break;
549                 }
550                 old_offset = dent->d_off;
551                 lstat(rel_to_abs(p9dev, dent->d_name, full_path), &st);
552                 stat2qid(&st, &qid);
553                 read = pdu->write_offset;
554                 virtio_p9_pdu_writef(pdu, "Qqbs", &qid, dent->d_off,
555                                      dent->d_type, dent->d_name);
556                 rcount += pdu->write_offset - read;
557                 dent = readdir(fid->dir);
558         }
559
560         pdu->write_offset = VIRTIO_9P_HDR_LEN;
561         virtio_p9_pdu_writef(pdu, "d", rcount);
562         *outlen = pdu->write_offset + rcount;
563         virtio_p9_set_reply_header(pdu, *outlen);
564         return;
565 err_out:
566         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
567         return;
568 }
569
570
571 static void virtio_p9_getattr(struct p9_dev *p9dev,
572                               struct p9_pdu *pdu, u32 *outlen)
573 {
574         u32 fid_val;
575         struct stat st;
576         u64 request_mask;
577         struct p9_fid *fid;
578         struct p9_stat_dotl statl;
579
580         virtio_p9_pdu_readf(pdu, "dq", &fid_val, &request_mask);
581         fid = get_fid(p9dev, fid_val);
582         if (lstat(fid->abs_path, &st) < 0)
583                 goto err_out;
584
585         virtio_p9_fill_stat(p9dev, &st, &statl);
586         virtio_p9_pdu_writef(pdu, "A", &statl);
587         *outlen = pdu->write_offset;
588         virtio_p9_set_reply_header(pdu, *outlen);
589         return;
590 err_out:
591         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
592         return;
593 }
594
595 /* FIXME!! from linux/fs.h */
596 /*
597  * Attribute flags.  These should be or-ed together to figure out what
598  * has been changed!
599  */
600 #define ATTR_MODE       (1 << 0)
601 #define ATTR_UID        (1 << 1)
602 #define ATTR_GID        (1 << 2)
603 #define ATTR_SIZE       (1 << 3)
604 #define ATTR_ATIME      (1 << 4)
605 #define ATTR_MTIME      (1 << 5)
606 #define ATTR_CTIME      (1 << 6)
607 #define ATTR_ATIME_SET  (1 << 7)
608 #define ATTR_MTIME_SET  (1 << 8)
609 #define ATTR_FORCE      (1 << 9) /* Not a change, but a change it */
610 #define ATTR_ATTR_FLAG  (1 << 10)
611 #define ATTR_KILL_SUID  (1 << 11)
612 #define ATTR_KILL_SGID  (1 << 12)
613 #define ATTR_FILE       (1 << 13)
614 #define ATTR_KILL_PRIV  (1 << 14)
615 #define ATTR_OPEN       (1 << 15) /* Truncating from open(O_TRUNC) */
616 #define ATTR_TIMES_SET  (1 << 16)
617
618 #define ATTR_MASK    127
619
620 static void virtio_p9_setattr(struct p9_dev *p9dev,
621                               struct p9_pdu *pdu, u32 *outlen)
622 {
623         int ret = 0;
624         u32 fid_val;
625         struct p9_fid *fid;
626         struct p9_iattr_dotl p9attr;
627
628         virtio_p9_pdu_readf(pdu, "dI", &fid_val, &p9attr);
629         fid = get_fid(p9dev, fid_val);
630
631         if (p9attr.valid & ATTR_MODE) {
632                 ret = chmod(fid->abs_path, p9attr.mode);
633                 if (ret < 0)
634                         goto err_out;
635         }
636         if (p9attr.valid & (ATTR_ATIME | ATTR_MTIME)) {
637                 struct timespec times[2];
638                 if (p9attr.valid & ATTR_ATIME) {
639                         if (p9attr.valid & ATTR_ATIME_SET) {
640                                 times[0].tv_sec = p9attr.atime_sec;
641                                 times[0].tv_nsec = p9attr.atime_nsec;
642                         } else {
643                                 times[0].tv_nsec = UTIME_NOW;
644                         }
645                 } else {
646                         times[0].tv_nsec = UTIME_OMIT;
647                 }
648                 if (p9attr.valid & ATTR_MTIME) {
649                         if (p9attr.valid & ATTR_MTIME_SET) {
650                                 times[1].tv_sec = p9attr.mtime_sec;
651                                 times[1].tv_nsec = p9attr.mtime_nsec;
652                         } else {
653                                 times[1].tv_nsec = UTIME_NOW;
654                         }
655                 } else
656                         times[1].tv_nsec = UTIME_OMIT;
657
658                 ret = utimensat(-1, fid->abs_path, times, AT_SYMLINK_NOFOLLOW);
659                 if (ret < 0)
660                         goto err_out;
661         }
662         /*
663          * If the only valid entry in iattr is ctime we can call
664          * chown(-1,-1) to update the ctime of the file
665          */
666         if ((p9attr.valid & (ATTR_UID | ATTR_GID)) ||
667             ((p9attr.valid & ATTR_CTIME)
668              && !((p9attr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
669                 if (!(p9attr.valid & ATTR_UID))
670                         p9attr.uid = -1;
671
672                 if (!(p9attr.valid & ATTR_GID))
673                         p9attr.gid = -1;
674
675                 ret = lchown(fid->abs_path, p9attr.uid, p9attr.gid);
676                 if (ret < 0)
677                         goto err_out;
678         }
679         if (p9attr.valid & (ATTR_SIZE)) {
680                 ret = truncate(fid->abs_path, p9attr.size);
681                 if (ret < 0)
682                         goto err_out;
683         }
684         *outlen = VIRTIO_9P_HDR_LEN;
685         virtio_p9_set_reply_header(pdu, *outlen);
686         return;
687 err_out:
688         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
689         return;
690 }
691
692 static void virtio_p9_write(struct p9_dev *p9dev,
693                             struct p9_pdu *pdu, u32 *outlen)
694 {
695
696         u64 offset;
697         u32 fid_val;
698         u32 count;
699         ssize_t res;
700         u16 iov_cnt;
701         void *iov_base;
702         size_t iov_len;
703         struct p9_fid *fid;
704         /* u32 fid + u64 offset + u32 count */
705         int twrite_size = sizeof(u32) + sizeof(u64) + sizeof(u32);
706
707         virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
708         fid = get_fid(p9dev, fid_val);
709
710         iov_base = pdu->out_iov[0].iov_base;
711         iov_len  = pdu->out_iov[0].iov_len;
712         iov_cnt  = pdu->out_iov_cnt;
713
714         /* Adjust the iovec to skip the header and meta data */
715         pdu->out_iov[0].iov_base += (sizeof(struct p9_msg) + twrite_size);
716         pdu->out_iov[0].iov_len -=  (sizeof(struct p9_msg) + twrite_size);
717         pdu->out_iov_cnt = virtio_p9_update_iov_cnt(pdu->out_iov, count,
718                                                     pdu->out_iov_cnt);
719         res = pwritev(fid->fd, pdu->out_iov, pdu->out_iov_cnt, offset);
720         /*
721          * Update the iov_base back, so that rest of
722          * pdu_readf works correctly.
723          */
724         pdu->out_iov[0].iov_base = iov_base;
725         pdu->out_iov[0].iov_len  = iov_len;
726         pdu->out_iov_cnt         = iov_cnt;
727
728         if (res < 0)
729                 goto err_out;
730         virtio_p9_pdu_writef(pdu, "d", res);
731         *outlen = pdu->write_offset;
732         virtio_p9_set_reply_header(pdu, *outlen);
733         return;
734 err_out:
735         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
736         return;
737 }
738
739 static void virtio_p9_remove(struct p9_dev *p9dev,
740                              struct p9_pdu *pdu, u32 *outlen)
741 {
742         int ret;
743         u32 fid_val;
744         struct p9_fid *fid;
745
746         virtio_p9_pdu_readf(pdu, "d", &fid_val);
747         fid = get_fid(p9dev, fid_val);
748
749         ret = remove(fid->abs_path);
750         if (ret < 0)
751                 goto err_out;
752         *outlen = pdu->write_offset;
753         virtio_p9_set_reply_header(pdu, *outlen);
754         return;
755
756 err_out:
757         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
758         return;
759 }
760
761 static void virtio_p9_rename(struct p9_dev *p9dev,
762                              struct p9_pdu *pdu, u32 *outlen)
763 {
764         int ret;
765         u32 fid_val, new_fid_val;
766         struct p9_fid *fid, *new_fid;
767         char full_path[PATH_MAX], *new_name;
768
769         virtio_p9_pdu_readf(pdu, "dds", &fid_val, &new_fid_val, &new_name);
770         fid = get_fid(p9dev, fid_val);
771         new_fid = get_fid(p9dev, new_fid_val);
772
773         sprintf(full_path, "%s/%s", new_fid->abs_path, new_name);
774         ret = rename(fid->abs_path, full_path);
775         if (ret < 0)
776                 goto err_out;
777         *outlen = pdu->write_offset;
778         virtio_p9_set_reply_header(pdu, *outlen);
779         return;
780
781 err_out:
782         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
783         return;
784 }
785
786 static void virtio_p9_readlink(struct p9_dev *p9dev,
787                                struct p9_pdu *pdu, u32 *outlen)
788 {
789         int ret;
790         u32 fid_val;
791         struct p9_fid *fid;
792         char target_path[PATH_MAX];
793
794         virtio_p9_pdu_readf(pdu, "d", &fid_val);
795         fid = get_fid(p9dev, fid_val);
796
797         memset(target_path, 0, PATH_MAX);
798         ret = readlink(fid->abs_path, target_path, PATH_MAX - 1);
799         if (ret < 0)
800                 goto err_out;
801
802         virtio_p9_pdu_writef(pdu, "s", target_path);
803         *outlen = pdu->write_offset;
804         virtio_p9_set_reply_header(pdu, *outlen);
805         return;
806 err_out:
807         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
808         return;
809 }
810
811 static void virtio_p9_statfs(struct p9_dev *p9dev,
812                              struct p9_pdu *pdu, u32 *outlen)
813 {
814         int ret;
815         u64 fsid;
816         u32 fid_val;
817         struct p9_fid *fid;
818         struct statfs stat_buf;
819
820         virtio_p9_pdu_readf(pdu, "d", &fid_val);
821         fid = get_fid(p9dev, fid_val);
822
823         ret = statfs(fid->abs_path, &stat_buf);
824         if (ret < 0)
825                 goto err_out;
826         /* FIXME!! f_blocks needs update based on client msize */
827         fsid = (unsigned int) stat_buf.f_fsid.__val[0] |
828                 (unsigned long long)stat_buf.f_fsid.__val[1] << 32;
829         virtio_p9_pdu_writef(pdu, "ddqqqqqqd", stat_buf.f_type,
830                              stat_buf.f_bsize, stat_buf.f_blocks,
831                              stat_buf.f_bfree, stat_buf.f_bavail,
832                              stat_buf.f_files, stat_buf.f_ffree,
833                              fsid, stat_buf.f_namelen);
834         *outlen = pdu->write_offset;
835         virtio_p9_set_reply_header(pdu, *outlen);
836         return;
837 err_out:
838         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
839         return;
840 }
841
842 static void virtio_p9_mknod(struct p9_dev *p9dev,
843                             struct p9_pdu *pdu, u32 *outlen)
844 {
845         int ret;
846         char *name;
847         struct stat st;
848         struct p9_fid *dfid;
849         struct p9_qid qid;
850         char full_path[PATH_MAX];
851         u32 fid_val, mode, major, minor, gid;
852
853         virtio_p9_pdu_readf(pdu, "dsdddd", &fid_val, &name, &mode,
854                             &major, &minor, &gid);
855
856         dfid = get_fid(p9dev, fid_val);
857         sprintf(full_path, "%s/%s", dfid->abs_path, name);
858         ret = mknod(full_path, mode, makedev(major, minor));
859         if (ret < 0)
860                 goto err_out;
861
862         if (lstat(full_path, &st) < 0)
863                 goto err_out;
864
865         ret = chmod(full_path, mode & 0777);
866         if (ret < 0)
867                 goto err_out;
868
869         stat2qid(&st, &qid);
870         virtio_p9_pdu_writef(pdu, "Q", &qid);
871         free(name);
872         *outlen = pdu->write_offset;
873         virtio_p9_set_reply_header(pdu, *outlen);
874         return;
875 err_out:
876         free(name);
877         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
878         return;
879 }
880
881 static void virtio_p9_fsync(struct p9_dev *p9dev,
882                             struct p9_pdu *pdu, u32 *outlen)
883 {
884         int ret;
885         struct p9_fid *fid;
886         u32 fid_val, datasync;
887
888         virtio_p9_pdu_readf(pdu, "dd", &fid_val, &datasync);
889         fid = get_fid(p9dev, fid_val);
890
891         if (datasync)
892                 ret = fdatasync(fid->fd);
893         else
894                 ret = fsync(fid->fd);
895         if (ret < 0)
896                 goto err_out;
897         *outlen = pdu->write_offset;
898         virtio_p9_set_reply_header(pdu, *outlen);
899         return;
900 err_out:
901         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
902         return;
903 }
904
905 static void virtio_p9_symlink(struct p9_dev *p9dev,
906                               struct p9_pdu *pdu, u32 *outlen)
907 {
908         int ret;
909         struct stat st;
910         u32 fid_val, gid;
911         struct p9_qid qid;
912         struct p9_fid *dfid;
913         char new_name[PATH_MAX];
914         char *old_path, *name;
915
916         virtio_p9_pdu_readf(pdu, "dssd", &fid_val, &name, &old_path, &gid);
917
918         dfid = get_fid(p9dev, fid_val);
919         sprintf(new_name, "%s/%s", dfid->abs_path, name);
920         ret = symlink(old_path, new_name);
921         if (ret < 0)
922                 goto err_out;
923
924         if (lstat(new_name, &st) < 0)
925                 goto err_out;
926
927         stat2qid(&st, &qid);
928         virtio_p9_pdu_writef(pdu, "Q", &qid);
929         free(name);
930         free(old_path);
931         *outlen = pdu->write_offset;
932         virtio_p9_set_reply_header(pdu, *outlen);
933         return;
934 err_out:
935         free(name);
936         free(old_path);
937         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
938         return;
939 }
940
941 static void virtio_p9_link(struct p9_dev *p9dev,
942                            struct p9_pdu *pdu, u32 *outlen)
943 {
944         int ret;
945         char *name;
946         u32 fid_val, dfid_val;
947         struct p9_fid *dfid, *fid;
948         char full_path[PATH_MAX];
949
950         virtio_p9_pdu_readf(pdu, "dds", &dfid_val, &fid_val, &name);
951
952         dfid = get_fid(p9dev, dfid_val);
953         fid =  get_fid(p9dev, fid_val);
954         sprintf(full_path, "%s/%s", dfid->abs_path, name);
955         ret = link(fid->abs_path, full_path);
956         if (ret < 0)
957                 goto err_out;
958         free(name);
959         *outlen = pdu->write_offset;
960         virtio_p9_set_reply_header(pdu, *outlen);
961         return;
962 err_out:
963         free(name);
964         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
965         return;
966
967 }
968
969 static void virtio_p9_lock(struct p9_dev *p9dev,
970                            struct p9_pdu *pdu, u32 *outlen)
971 {
972         u8 ret;
973         u32 fid_val;
974         struct p9_flock flock;
975
976         virtio_p9_pdu_readf(pdu, "dbdqqds", &fid_val, &flock.type,
977                             &flock.flags, &flock.start, &flock.length,
978                             &flock.proc_id, &flock.client_id);
979
980         /* Just return success */
981         ret = P9_LOCK_SUCCESS;
982         virtio_p9_pdu_writef(pdu, "d", ret);
983         *outlen = pdu->write_offset;
984         virtio_p9_set_reply_header(pdu, *outlen);
985         free(flock.client_id);
986         return;
987 }
988
989 static void virtio_p9_getlock(struct p9_dev *p9dev,
990                               struct p9_pdu *pdu, u32 *outlen)
991 {
992         u32 fid_val;
993         struct p9_getlock glock;
994         virtio_p9_pdu_readf(pdu, "dbqqds", &fid_val, &glock.type,
995                             &glock.start, &glock.length, &glock.proc_id,
996                             &glock.client_id);
997
998         /* Just return success */
999         glock.type = F_UNLCK;
1000         virtio_p9_pdu_writef(pdu, "bqqds", glock.type,
1001                              glock.start, glock.length, glock.proc_id,
1002                              glock.client_id);
1003         *outlen = pdu->write_offset;
1004         virtio_p9_set_reply_header(pdu, *outlen);
1005         free(glock.client_id);
1006         return;
1007 }
1008
1009 static int virtio_p9_ancestor(char *path, char *ancestor)
1010 {
1011         int size = strlen(ancestor);
1012         if (!strncmp(path, ancestor, size)) {
1013                 /*
1014                  * Now check whether ancestor is a full name or
1015                  * or directory component and not just part
1016                  * of a name.
1017                  */
1018                 if (path[size] == '\0' || path[size] == '/')
1019                         return 1;
1020         }
1021         return 0;
1022 }
1023
1024 static void virtio_p9_fix_path(char *fid_path, char *old_name, char *new_name)
1025 {
1026         char tmp_name[PATH_MAX];
1027         size_t rp_sz = strlen(old_name);
1028
1029         if (rp_sz == strlen(fid_path)) {
1030                 /* replace the full name */
1031                 strcpy(fid_path, new_name);
1032                 return;
1033         }
1034         /* save the trailing path details */
1035         strcpy(tmp_name, fid_path + rp_sz);
1036         sprintf(fid_path, "%s%s", new_name, tmp_name);
1037         return;
1038 }
1039
1040 static void rename_fids(struct p9_dev *p9dev, char *old_name, char *new_name)
1041 {
1042         struct rb_node *node = rb_first(&p9dev->fids);
1043
1044         while (node) {
1045                 struct p9_fid *fid = rb_entry(node, struct p9_fid, node);
1046
1047                 if (fid->fid != P9_NOFID && virtio_p9_ancestor(fid->path, old_name)) {
1048                                 virtio_p9_fix_path(fid->path, old_name, new_name);
1049                 }
1050                 node = rb_next(node);
1051         }
1052 }
1053
1054 static void virtio_p9_renameat(struct p9_dev *p9dev,
1055                                struct p9_pdu *pdu, u32 *outlen)
1056 {
1057         int ret;
1058         char *old_name, *new_name;
1059         u32 old_dfid_val, new_dfid_val;
1060         struct p9_fid *old_dfid, *new_dfid;
1061         char old_full_path[PATH_MAX], new_full_path[PATH_MAX];
1062
1063
1064         virtio_p9_pdu_readf(pdu, "dsds", &old_dfid_val, &old_name,
1065                             &new_dfid_val, &new_name);
1066
1067         old_dfid = get_fid(p9dev, old_dfid_val);
1068         new_dfid = get_fid(p9dev, new_dfid_val);
1069
1070         sprintf(old_full_path, "%s/%s", old_dfid->abs_path, old_name);
1071         sprintf(new_full_path, "%s/%s", new_dfid->abs_path, new_name);
1072         ret = rename(old_full_path, new_full_path);
1073         if (ret < 0)
1074                 goto err_out;
1075         /*
1076          * Now fix path in other fids, if the renamed path is part of
1077          * that.
1078          */
1079         rename_fids(p9dev, old_name, new_name);
1080         free(old_name);
1081         free(new_name);
1082         *outlen = pdu->write_offset;
1083         virtio_p9_set_reply_header(pdu, *outlen);
1084         return;
1085 err_out:
1086         free(old_name);
1087         free(new_name);
1088         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
1089         return;
1090 }
1091
1092 static void virtio_p9_unlinkat(struct p9_dev *p9dev,
1093                                struct p9_pdu *pdu, u32 *outlen)
1094 {
1095         int ret;
1096         char *name;
1097         u32 fid_val, flags;
1098         struct p9_fid *fid;
1099         char full_path[PATH_MAX];
1100
1101         virtio_p9_pdu_readf(pdu, "dsd", &fid_val, &name, &flags);
1102         fid = get_fid(p9dev, fid_val);
1103
1104         sprintf(full_path, "%s/%s", fid->abs_path, name);
1105         ret = remove(full_path);
1106         if (ret < 0)
1107                 goto err_out;
1108         free(name);
1109         *outlen = pdu->write_offset;
1110         virtio_p9_set_reply_header(pdu, *outlen);
1111         return;
1112 err_out:
1113         free(name);
1114         virtio_p9_error_reply(p9dev, pdu, errno, outlen);
1115         return;
1116 }
1117
1118 static void virtio_p9_flush(struct p9_dev *p9dev,
1119                                 struct p9_pdu *pdu, u32 *outlen)
1120 {
1121         u16 tag, oldtag;
1122
1123         virtio_p9_pdu_readf(pdu, "ww", &tag, &oldtag);
1124         virtio_p9_pdu_writef(pdu, "w", tag);
1125         *outlen = pdu->write_offset;
1126         virtio_p9_set_reply_header(pdu, *outlen);
1127
1128         return;
1129 }
1130
1131 static void virtio_p9_eopnotsupp(struct p9_dev *p9dev,
1132                                  struct p9_pdu *pdu, u32 *outlen)
1133 {
1134         return virtio_p9_error_reply(p9dev, pdu, EOPNOTSUPP, outlen);
1135 }
1136
1137 typedef void p9_handler(struct p9_dev *p9dev,
1138                         struct p9_pdu *pdu, u32 *outlen);
1139
1140 /* FIXME should be removed when merging with latest linus tree */
1141 #define P9_TRENAMEAT 74
1142 #define P9_TUNLINKAT 76
1143
1144 static p9_handler *virtio_9p_dotl_handler [] = {
1145         [P9_TREADDIR]     = virtio_p9_readdir,
1146         [P9_TSTATFS]      = virtio_p9_statfs,
1147         [P9_TGETATTR]     = virtio_p9_getattr,
1148         [P9_TSETATTR]     = virtio_p9_setattr,
1149         [P9_TXATTRWALK]   = virtio_p9_eopnotsupp,
1150         [P9_TXATTRCREATE] = virtio_p9_eopnotsupp,
1151         [P9_TMKNOD]       = virtio_p9_mknod,
1152         [P9_TLOCK]        = virtio_p9_lock,
1153         [P9_TGETLOCK]     = virtio_p9_getlock,
1154         [P9_TRENAMEAT]    = virtio_p9_renameat,
1155         [P9_TREADLINK]    = virtio_p9_readlink,
1156         [P9_TUNLINKAT]    = virtio_p9_unlinkat,
1157         [P9_TMKDIR]       = virtio_p9_mkdir,
1158         [P9_TVERSION]     = virtio_p9_version,
1159         [P9_TLOPEN]       = virtio_p9_open,
1160         [P9_TATTACH]      = virtio_p9_attach,
1161         [P9_TWALK]        = virtio_p9_walk,
1162         [P9_TCLUNK]       = virtio_p9_clunk,
1163         [P9_TFSYNC]       = virtio_p9_fsync,
1164         [P9_TREAD]        = virtio_p9_read,
1165         [P9_TFLUSH]       = virtio_p9_flush,
1166         [P9_TLINK]        = virtio_p9_link,
1167         [P9_TSYMLINK]     = virtio_p9_symlink,
1168         [P9_TLCREATE]     = virtio_p9_create,
1169         [P9_TWRITE]       = virtio_p9_write,
1170         [P9_TREMOVE]      = virtio_p9_remove,
1171         [P9_TRENAME]      = virtio_p9_rename,
1172 };
1173
1174 static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
1175 {
1176         struct p9_pdu *pdu = calloc(1, sizeof(*pdu));
1177         if (!pdu)
1178                 return NULL;
1179
1180         /* skip the pdu header p9_msg */
1181         pdu->read_offset        = VIRTIO_9P_HDR_LEN;
1182         pdu->write_offset       = VIRTIO_9P_HDR_LEN;
1183         pdu->queue_head         = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
1184                                         pdu->out_iov, &pdu->in_iov_cnt, &pdu->out_iov_cnt);
1185         return pdu;
1186 }
1187
1188 static u8 virtio_p9_get_cmd(struct p9_pdu *pdu)
1189 {
1190         struct p9_msg *msg;
1191         /*
1192          * we can peek directly into pdu for a u8
1193          * value. The host endianess won't be an issue
1194          */
1195         msg = pdu->out_iov[0].iov_base;
1196         return msg->cmd;
1197 }
1198
1199 static bool virtio_p9_do_io_request(struct kvm *kvm, struct p9_dev_job *job)
1200 {
1201         u8 cmd;
1202         u32 len = 0;
1203         p9_handler *handler;
1204         struct p9_dev *p9dev;
1205         struct virt_queue *vq;
1206         struct p9_pdu *p9pdu;
1207
1208         vq = job->vq;
1209         p9dev = job->p9dev;
1210
1211         p9pdu = virtio_p9_pdu_init(kvm, vq);
1212         cmd = virtio_p9_get_cmd(p9pdu);
1213
1214         if ((cmd >= ARRAY_SIZE(virtio_9p_dotl_handler)) ||
1215             !virtio_9p_dotl_handler[cmd])
1216                 handler = virtio_p9_eopnotsupp;
1217         else
1218                 handler = virtio_9p_dotl_handler[cmd];
1219
1220         handler(p9dev, p9pdu, &len);
1221         virt_queue__set_used_elem(vq, p9pdu->queue_head, len);
1222         free(p9pdu);
1223         return true;
1224 }
1225
1226 static void virtio_p9_do_io(struct kvm *kvm, void *param)
1227 {
1228         struct p9_dev_job *job = (struct p9_dev_job *)param;
1229         struct p9_dev *p9dev   = job->p9dev;
1230         struct virt_queue *vq  = job->vq;
1231
1232         while (virt_queue__available(vq)) {
1233                 virtio_p9_do_io_request(kvm, job);
1234                 p9dev->vdev.ops->signal_vq(kvm, &p9dev->vdev, vq - p9dev->vqs);
1235         }
1236 }
1237
1238 static u8 *get_config(struct kvm *kvm, void *dev)
1239 {
1240         struct p9_dev *p9dev = dev;
1241
1242         return ((u8 *)(p9dev->config));
1243 }
1244
1245 static u32 get_host_features(struct kvm *kvm, void *dev)
1246 {
1247         return 1 << VIRTIO_9P_MOUNT_TAG;
1248 }
1249
1250 static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
1251 {
1252         struct p9_dev *p9dev = dev;
1253
1254         p9dev->features = features;
1255 }
1256
1257 static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
1258 {
1259         struct p9_dev *p9dev = dev;
1260         struct p9_dev_job *job;
1261         struct virt_queue *queue;
1262         void *p;
1263
1264         compat__remove_message(compat_id);
1265
1266         queue           = &p9dev->vqs[vq];
1267         queue->pfn      = pfn;
1268         p               = guest_pfn_to_host(kvm, queue->pfn);
1269         job             = &p9dev->jobs[vq];
1270
1271         vring_init(&queue->vring, VIRTQUEUE_NUM, p, VIRTIO_PCI_VRING_ALIGN);
1272
1273         *job            = (struct p9_dev_job) {
1274                 .vq             = queue,
1275                 .p9dev          = p9dev,
1276         };
1277         thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
1278
1279         return 0;
1280 }
1281
1282 static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
1283 {
1284         struct p9_dev *p9dev = dev;
1285
1286         thread_pool__do_job(&p9dev->jobs[vq].job_id);
1287
1288         return 0;
1289 }
1290
1291 static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
1292 {
1293         struct p9_dev *p9dev = dev;
1294
1295         return p9dev->vqs[vq].pfn;
1296 }
1297
1298 static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
1299 {
1300         return VIRTQUEUE_NUM;
1301 }
1302
1303 struct virtio_ops p9_dev_virtio_ops = (struct virtio_ops) {
1304         .get_config             = get_config,
1305         .get_host_features      = get_host_features,
1306         .set_guest_features     = set_guest_features,
1307         .init_vq                = init_vq,
1308         .notify_vq              = notify_vq,
1309         .get_pfn_vq             = get_pfn_vq,
1310         .get_size_vq            = get_size_vq,
1311 };
1312
1313 int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset)
1314 {
1315         char *tag_name;
1316         char tmp[PATH_MAX];
1317         struct kvm *kvm = opt->ptr;
1318
1319         /*
1320          * 9p dir can be of the form dirname,tag_name or
1321          * just dirname. In the later case we use the
1322          * default tag name
1323          */
1324         tag_name = strstr(arg, ",");
1325         if (tag_name) {
1326                 *tag_name = '\0';
1327                 tag_name++;
1328         }
1329         if (realpath(arg, tmp)) {
1330                 if (virtio_9p__register(kvm, tmp, tag_name) < 0)
1331                         die("Unable to initialize virtio 9p");
1332         } else
1333                 die("Failed resolving 9p path");
1334         return 0;
1335 }
1336
1337 int virtio_9p_img_name_parser(const struct option *opt, const char *arg, int unset)
1338 {
1339         char path[PATH_MAX];
1340         struct stat st;
1341         struct kvm *kvm = opt->ptr;
1342
1343         if (stat(arg, &st) == 0 &&
1344             S_ISDIR(st.st_mode)) {
1345                 char tmp[PATH_MAX];
1346
1347                 if (kvm->cfg.using_rootfs)
1348                         die("Please use only one rootfs directory atmost");
1349
1350                 if (realpath(arg, tmp) == 0 ||
1351                     virtio_9p__register(kvm, tmp, "/dev/root") < 0)
1352                         die("Unable to initialize virtio 9p");
1353                 kvm->cfg.using_rootfs = 1;
1354                 return 0;
1355         }
1356
1357         snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg);
1358
1359         if (stat(path, &st) == 0 &&
1360             S_ISDIR(st.st_mode)) {
1361                 char tmp[PATH_MAX];
1362
1363                 if (kvm->cfg.using_rootfs)
1364                         die("Please use only one rootfs directory atmost");
1365
1366                 if (realpath(path, tmp) == 0 ||
1367                     virtio_9p__register(kvm, tmp, "/dev/root") < 0)
1368                         die("Unable to initialize virtio 9p");
1369                 if (virtio_9p__register(kvm, "/", "hostfs") < 0)
1370                         die("Unable to initialize virtio 9p");
1371                 kvm_setup_resolv(arg);
1372                 kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1;
1373                 kvm->cfg.custom_rootfs_name = arg;
1374                 return 0;
1375         }
1376
1377         return -1;
1378 }
1379
1380 int virtio_9p__init(struct kvm *kvm)
1381 {
1382         struct p9_dev *p9dev;
1383
1384         list_for_each_entry(p9dev, &devs, list) {
1385                 virtio_init(kvm, p9dev, &p9dev->vdev, &p9_dev_virtio_ops,
1386                             VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_9P, VIRTIO_ID_9P, PCI_CLASS_9P);
1387         }
1388
1389         return 0;
1390 }
1391 virtio_dev_init(virtio_9p__init);
1392
1393 int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name)
1394 {
1395         struct p9_dev *p9dev;
1396         int err = 0;
1397
1398         p9dev = calloc(1, sizeof(*p9dev));
1399         if (!p9dev)
1400                 return -ENOMEM;
1401
1402         if (!tag_name)
1403                 tag_name = VIRTIO_9P_DEFAULT_TAG;
1404
1405         p9dev->config = calloc(1, sizeof(*p9dev->config) + strlen(tag_name) + 1);
1406         if (p9dev->config == NULL) {
1407                 err = -ENOMEM;
1408                 goto free_p9dev;
1409         }
1410
1411         strcpy(p9dev->root_dir, root);
1412         p9dev->config->tag_len = strlen(tag_name);
1413         if (p9dev->config->tag_len > MAX_TAG_LEN) {
1414                 err = -EINVAL;
1415                 goto free_p9dev_config;
1416         }
1417
1418         memcpy(&p9dev->config->tag, tag_name, strlen(tag_name));
1419
1420         list_add(&p9dev->list, &devs);
1421
1422         if (compat_id == -1)
1423                 compat_id = virtio_compat_add_message("virtio-9p", "CONFIG_NET_9P_VIRTIO");
1424
1425         return err;
1426
1427 free_p9dev_config:
1428         free(p9dev->config);
1429 free_p9dev:
1430         free(p9dev);
1431         return err;
1432 }