kvm tools: Add ivshmem device
[linux-2.6/next.git] / tools / kvm / virtio / 9p.c
blob0dffc7a152825d7d08fb9a4e2321d0e1100558eb
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"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <fcntl.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <sys/vfs.h>
18 #include <linux/virtio_ring.h>
19 #include <linux/virtio_9p.h>
20 #include <net/9p/9p.h>
22 static LIST_HEAD(devs);
24 /* Warning: Immediately use value returned from this function */
25 static const char *rel_to_abs(struct p9_dev *p9dev,
26 const char *path, char *abs_path)
28 sprintf(abs_path, "%s/%s", p9dev->root_dir, path);
30 return abs_path;
33 static void stat2qid(struct stat *st, struct p9_qid *qid)
35 *qid = (struct p9_qid) {
36 .path = st->st_ino,
37 .version = st->st_mtime,
40 if (S_ISDIR(st->st_mode))
41 qid->type |= P9_QTDIR;
44 static void close_fid(struct p9_dev *p9dev, u32 fid)
46 if (p9dev->fids[fid].fd > 0) {
47 close(p9dev->fids[fid].fd);
48 p9dev->fids[fid].fd = -1;
50 if (p9dev->fids[fid].dir) {
51 closedir(p9dev->fids[fid].dir);
52 p9dev->fids[fid].dir = NULL;
54 p9dev->fids[fid].fid = P9_NOFID;
57 static void virtio_p9_set_reply_header(struct p9_pdu *pdu, u32 size)
59 u8 cmd;
60 u16 tag;
62 pdu->read_offset = sizeof(u32);
63 virtio_p9_pdu_readf(pdu, "bw", &cmd, &tag);
64 pdu->write_offset = 0;
65 /* cmd + 1 is the reply message */
66 virtio_p9_pdu_writef(pdu, "dbw", size, cmd + 1, tag);
69 static u16 virtio_p9_update_iov_cnt(struct iovec iov[], u32 count, int iov_cnt)
71 int i;
72 u32 total = 0;
73 for (i = 0; (i < iov_cnt) && (total < count); i++) {
74 if (total + iov[i].iov_len > count) {
75 /* we don't need this iov fully */
76 iov[i].iov_len -= ((total + iov[i].iov_len) - count);
77 i++;
78 break;
80 total += iov[i].iov_len;
82 return i;
85 static void virtio_p9_error_reply(struct p9_dev *p9dev,
86 struct p9_pdu *pdu, int err, u32 *outlen)
88 u16 tag;
90 pdu->write_offset = VIRTIO_P9_HDR_LEN;
91 virtio_p9_pdu_writef(pdu, "d", err);
92 *outlen = pdu->write_offset;
94 /* read the tag from input */
95 pdu->read_offset = sizeof(u32) + sizeof(u8);
96 virtio_p9_pdu_readf(pdu, "w", &tag);
98 /* Update the header */
99 pdu->write_offset = 0;
100 virtio_p9_pdu_writef(pdu, "dbw", *outlen, P9_RLERROR, tag);
103 static void virtio_p9_version(struct p9_dev *p9dev,
104 struct p9_pdu *pdu, u32 *outlen)
106 u32 msize;
107 char *version;
108 virtio_p9_pdu_readf(pdu, "ds", &msize, &version);
110 * reply with the same msize the client sent us
111 * Error out if the request is not for 9P2000.L
113 if (!strcmp(version, VIRTIO_P9_VERSION_DOTL))
114 virtio_p9_pdu_writef(pdu, "ds", msize, version);
115 else
116 virtio_p9_pdu_writef(pdu, "ds", msize, "unknown");
118 *outlen = pdu->write_offset;
119 virtio_p9_set_reply_header(pdu, *outlen);
120 free(version);
121 return;
124 static void virtio_p9_clunk(struct p9_dev *p9dev,
125 struct p9_pdu *pdu, u32 *outlen)
127 u32 fid;
129 virtio_p9_pdu_readf(pdu, "d", &fid);
130 close_fid(p9dev, fid);
132 *outlen = pdu->write_offset;
133 virtio_p9_set_reply_header(pdu, *outlen);
134 return;
138 * FIXME!! Need to map to protocol independent value. Upstream
139 * 9p also have the same BUG
141 static int virtio_p9_openflags(int flags)
143 flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT | O_DIRECT);
144 flags |= O_NOFOLLOW;
145 return flags;
148 static void virtio_p9_open(struct p9_dev *p9dev,
149 struct p9_pdu *pdu, u32 *outlen)
151 u32 fid, flags;
152 struct stat st;
153 struct p9_qid qid;
154 struct p9_fid *new_fid;
157 virtio_p9_pdu_readf(pdu, "dd", &fid, &flags);
158 new_fid = &p9dev->fids[fid];
160 if (lstat(new_fid->abs_path, &st) < 0)
161 goto err_out;
163 stat2qid(&st, &qid);
165 if (new_fid->is_dir) {
166 new_fid->dir = opendir(new_fid->abs_path);
167 if (!new_fid->dir)
168 goto err_out;
169 } else {
170 new_fid->fd = open(new_fid->abs_path,
171 virtio_p9_openflags(flags));
172 if (new_fid->fd < 0)
173 goto err_out;
175 /* FIXME!! need ot send proper iounit */
176 virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
178 *outlen = pdu->write_offset;
179 virtio_p9_set_reply_header(pdu, *outlen);
180 return;
181 err_out:
182 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
183 return;
186 static void virtio_p9_create(struct p9_dev *p9dev,
187 struct p9_pdu *pdu, u32 *outlen)
189 int fd, ret;
190 char *name;
191 struct stat st;
192 struct p9_qid qid;
193 struct p9_fid *dfid;
194 char full_path[PATH_MAX];
195 u32 dfid_val, flags, mode, gid;
197 virtio_p9_pdu_readf(pdu, "dsddd", &dfid_val,
198 &name, &flags, &mode, &gid);
199 dfid = &p9dev->fids[dfid_val];
201 flags = virtio_p9_openflags(flags);
203 sprintf(full_path, "%s/%s", dfid->abs_path, name);
204 fd = open(full_path, flags | O_CREAT, mode);
205 if (fd < 0)
206 goto err_out;
207 close_fid(p9dev, dfid_val);
208 dfid->fd = fd;
210 if (lstat(full_path, &st) < 0)
211 goto err_out;
213 ret = chmod(full_path, mode & 0777);
214 if (ret < 0)
215 goto err_out;
217 ret = lchown(full_path, dfid->uid, gid);
218 if (ret < 0)
219 goto err_out;
221 sprintf(dfid->path, "%s/%s", dfid->path, name);
222 stat2qid(&st, &qid);
223 virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
224 *outlen = pdu->write_offset;
225 virtio_p9_set_reply_header(pdu, *outlen);
226 free(name);
227 return;
228 err_out:
229 free(name);
230 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
231 return;
234 static void virtio_p9_mkdir(struct p9_dev *p9dev,
235 struct p9_pdu *pdu, u32 *outlen)
237 int ret;
238 char *name;
239 struct stat st;
240 struct p9_qid qid;
241 struct p9_fid *dfid;
242 char full_path[PATH_MAX];
243 u32 dfid_val, mode, gid;
245 virtio_p9_pdu_readf(pdu, "dsdd", &dfid_val,
246 &name, &mode, &gid);
247 dfid = &p9dev->fids[dfid_val];
249 sprintf(full_path, "%s/%s", dfid->abs_path, name);
250 ret = mkdir(full_path, mode);
251 if (ret < 0)
252 goto err_out;
254 if (lstat(full_path, &st) < 0)
255 goto err_out;
257 ret = chmod(full_path, mode & 0777);
258 if (ret < 0)
259 goto err_out;
261 ret = lchown(full_path, dfid->uid, gid);
262 if (ret < 0)
263 goto err_out;
265 stat2qid(&st, &qid);
266 virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
267 *outlen = pdu->write_offset;
268 virtio_p9_set_reply_header(pdu, *outlen);
269 free(name);
270 return;
271 err_out:
272 free(name);
273 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
274 return;
277 static void virtio_p9_walk(struct p9_dev *p9dev,
278 struct p9_pdu *pdu, u32 *outlen)
280 u8 i;
281 u16 nwqid;
282 char *str;
283 u16 nwname;
284 struct p9_qid wqid;
285 struct p9_fid *new_fid;
286 u32 fid_val, newfid_val;
289 virtio_p9_pdu_readf(pdu, "ddw", &fid_val, &newfid_val, &nwname);
290 new_fid = &p9dev->fids[newfid_val];
292 nwqid = 0;
293 if (nwname) {
294 struct p9_fid *fid = &p9dev->fids[fid_val];
296 strcpy(new_fid->path, fid->path);
297 /* skip the space for count */
298 pdu->write_offset += sizeof(u16);
299 for (i = 0; i < nwname; i++) {
300 struct stat st;
301 char tmp[PATH_MAX] = {0};
302 char full_path[PATH_MAX];
304 virtio_p9_pdu_readf(pdu, "s", &str);
306 /* Format the new path we're 'walk'ing into */
307 sprintf(tmp, "%s/%s", new_fid->path, str);
308 if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
309 goto err_out;
311 stat2qid(&st, &wqid);
312 new_fid->is_dir = S_ISDIR(st.st_mode);
313 strcpy(new_fid->path, tmp);
314 new_fid->fid = newfid_val;
315 new_fid->uid = fid->uid;
316 nwqid++;
317 virtio_p9_pdu_writef(pdu, "Q", &wqid);
319 } else {
321 * update write_offset so our outlen get correct value
323 pdu->write_offset += sizeof(u16);
324 new_fid->is_dir = p9dev->fids[fid_val].is_dir;
325 strcpy(new_fid->path, p9dev->fids[fid_val].path);
326 new_fid->fid = newfid_val;
327 new_fid->uid = p9dev->fids[fid_val].uid;
329 *outlen = pdu->write_offset;
330 pdu->write_offset = VIRTIO_P9_HDR_LEN;
331 virtio_p9_pdu_writef(pdu, "d", nwqid);
332 virtio_p9_set_reply_header(pdu, *outlen);
333 return;
334 err_out:
335 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
336 return;
339 static void virtio_p9_attach(struct p9_dev *p9dev,
340 struct p9_pdu *pdu, u32 *outlen)
342 int i;
343 char *uname;
344 char *aname;
345 struct stat st;
346 struct p9_qid qid;
347 struct p9_fid *fid;
348 u32 fid_val, afid, uid;
350 virtio_p9_pdu_readf(pdu, "ddssd", &fid_val, &afid,
351 &uname, &aname, &uid);
353 /* Reset everything */
354 for (i = 0; i < VIRTIO_P9_MAX_FID; i++)
355 p9dev->fids[i].fid = P9_NOFID;
357 if (lstat(p9dev->root_dir, &st) < 0)
358 goto err_out;
360 stat2qid(&st, &qid);
362 fid = &p9dev->fids[fid_val];
363 fid->fid = fid_val;
364 fid->uid = uid;
365 fid->is_dir = 1;
366 strcpy(fid->path, "/");
368 virtio_p9_pdu_writef(pdu, "Q", &qid);
369 *outlen = pdu->write_offset;
370 virtio_p9_set_reply_header(pdu, *outlen);
371 return;
372 err_out:
373 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
374 return;
377 static void virtio_p9_fill_stat(struct p9_dev *p9dev,
378 struct stat *st, struct p9_stat_dotl *statl)
380 memset(statl, 0, sizeof(*statl));
381 statl->st_mode = st->st_mode;
382 statl->st_nlink = st->st_nlink;
383 statl->st_uid = st->st_uid;
384 statl->st_gid = st->st_gid;
385 statl->st_rdev = st->st_rdev;
386 statl->st_size = st->st_size;
387 statl->st_blksize = st->st_blksize;
388 statl->st_blocks = st->st_blocks;
389 statl->st_atime_sec = st->st_atime;
390 statl->st_atime_nsec = st->st_atim.tv_nsec;
391 statl->st_mtime_sec = st->st_mtime;
392 statl->st_mtime_nsec = st->st_mtim.tv_nsec;
393 statl->st_ctime_sec = st->st_ctime;
394 statl->st_ctime_nsec = st->st_ctim.tv_nsec;
395 /* Currently we only support BASIC fields in stat */
396 statl->st_result_mask = P9_STATS_BASIC;
397 stat2qid(st, &statl->qid);
400 static void virtio_p9_read(struct p9_dev *p9dev,
401 struct p9_pdu *pdu, u32 *outlen)
403 u64 offset;
404 u32 fid_val;
405 u16 iov_cnt;
406 void *iov_base;
407 size_t iov_len;
408 u32 count, rcount;
409 struct p9_fid *fid;
412 rcount = 0;
413 virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
414 fid = &p9dev->fids[fid_val];
416 iov_base = pdu->in_iov[0].iov_base;
417 iov_len = pdu->in_iov[0].iov_len;
418 iov_cnt = pdu->in_iov_cnt;
419 pdu->in_iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
420 pdu->in_iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
421 pdu->in_iov_cnt = virtio_p9_update_iov_cnt(pdu->in_iov,
422 count,
423 pdu->in_iov_cnt);
424 rcount = preadv(fid->fd, pdu->in_iov,
425 pdu->in_iov_cnt, offset);
426 if (rcount > count)
427 rcount = count;
429 * Update the iov_base back, so that rest of
430 * pdu_writef works correctly.
432 pdu->in_iov[0].iov_base = iov_base;
433 pdu->in_iov[0].iov_len = iov_len;
434 pdu->in_iov_cnt = iov_cnt;
436 pdu->write_offset = VIRTIO_P9_HDR_LEN;
437 virtio_p9_pdu_writef(pdu, "d", rcount);
438 *outlen = pdu->write_offset + rcount;
439 virtio_p9_set_reply_header(pdu, *outlen);
440 return;
443 static int virtio_p9_dentry_size(struct dirent *dent)
446 * Size of each dirent:
447 * qid(13) + offset(8) + type(1) + name_len(2) + name
449 return 24 + strlen(dent->d_name);
452 static void virtio_p9_readdir(struct p9_dev *p9dev,
453 struct p9_pdu *pdu, u32 *outlen)
455 u32 fid_val;
456 u32 count, rcount;
457 struct stat st;
458 struct p9_fid *fid;
459 struct dirent *dent;
460 char full_path[PATH_MAX];
461 u64 offset, old_offset;
463 rcount = 0;
464 virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
465 fid = &p9dev->fids[fid_val];
467 if (!fid->is_dir) {
468 errno = -EINVAL;
469 goto err_out;
472 /* Move the offset specified */
473 seekdir(fid->dir, offset);
475 old_offset = offset;
476 /* If reading a dir, fill the buffer with p9_stat entries */
477 dent = readdir(fid->dir);
479 /* Skip the space for writing count */
480 pdu->write_offset += sizeof(u32);
481 while (dent) {
482 u32 read;
483 struct p9_qid qid;
485 if ((rcount + virtio_p9_dentry_size(dent)) > count) {
486 /* seek to the previous offset and return */
487 seekdir(fid->dir, old_offset);
488 break;
490 old_offset = dent->d_off;
491 lstat(rel_to_abs(p9dev, dent->d_name, full_path), &st);
492 stat2qid(&st, &qid);
493 read = pdu->write_offset;
494 virtio_p9_pdu_writef(pdu, "Qqbs", &qid, dent->d_off,
495 dent->d_type, dent->d_name);
496 rcount += pdu->write_offset - read;
497 dent = readdir(fid->dir);
500 pdu->write_offset = VIRTIO_P9_HDR_LEN;
501 virtio_p9_pdu_writef(pdu, "d", rcount);
502 *outlen = pdu->write_offset + rcount;
503 virtio_p9_set_reply_header(pdu, *outlen);
504 return;
505 err_out:
506 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
507 return;
511 static void virtio_p9_getattr(struct p9_dev *p9dev,
512 struct p9_pdu *pdu, u32 *outlen)
514 u32 fid_val;
515 struct stat st;
516 u64 request_mask;
517 struct p9_fid *fid;
518 struct p9_stat_dotl statl;
520 virtio_p9_pdu_readf(pdu, "dq", &fid_val, &request_mask);
521 fid = &p9dev->fids[fid_val];
522 if (lstat(fid->abs_path, &st) < 0)
523 goto err_out;
525 virtio_p9_fill_stat(p9dev, &st, &statl);
526 virtio_p9_pdu_writef(pdu, "A", &statl);
527 *outlen = pdu->write_offset;
528 virtio_p9_set_reply_header(pdu, *outlen);
529 return;
530 err_out:
531 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
532 return;
535 /* FIXME!! from linux/fs.h */
537 * Attribute flags. These should be or-ed together to figure out what
538 * has been changed!
540 #define ATTR_MODE (1 << 0)
541 #define ATTR_UID (1 << 1)
542 #define ATTR_GID (1 << 2)
543 #define ATTR_SIZE (1 << 3)
544 #define ATTR_ATIME (1 << 4)
545 #define ATTR_MTIME (1 << 5)
546 #define ATTR_CTIME (1 << 6)
547 #define ATTR_ATIME_SET (1 << 7)
548 #define ATTR_MTIME_SET (1 << 8)
549 #define ATTR_FORCE (1 << 9) /* Not a change, but a change it */
550 #define ATTR_ATTR_FLAG (1 << 10)
551 #define ATTR_KILL_SUID (1 << 11)
552 #define ATTR_KILL_SGID (1 << 12)
553 #define ATTR_FILE (1 << 13)
554 #define ATTR_KILL_PRIV (1 << 14)
555 #define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
556 #define ATTR_TIMES_SET (1 << 16)
558 #define ATTR_MASK 127
560 static void virtio_p9_setattr(struct p9_dev *p9dev,
561 struct p9_pdu *pdu, u32 *outlen)
563 int ret = 0;
564 u32 fid_val;
565 struct p9_fid *fid;
566 struct p9_iattr_dotl p9attr;
568 virtio_p9_pdu_readf(pdu, "dI", &fid_val, &p9attr);
569 fid = &p9dev->fids[fid_val];
571 if (p9attr.valid & ATTR_MODE) {
572 ret = chmod(fid->abs_path, p9attr.mode);
573 if (ret < 0)
574 goto err_out;
576 if (p9attr.valid & (ATTR_ATIME | ATTR_MTIME)) {
577 struct timespec times[2];
578 if (p9attr.valid & ATTR_ATIME) {
579 if (p9attr.valid & ATTR_ATIME_SET) {
580 times[0].tv_sec = p9attr.atime_sec;
581 times[0].tv_nsec = p9attr.atime_nsec;
582 } else {
583 times[0].tv_nsec = UTIME_NOW;
585 } else {
586 times[0].tv_nsec = UTIME_OMIT;
588 if (p9attr.valid & ATTR_MTIME) {
589 if (p9attr.valid & ATTR_MTIME_SET) {
590 times[1].tv_sec = p9attr.mtime_sec;
591 times[1].tv_nsec = p9attr.mtime_nsec;
592 } else {
593 times[1].tv_nsec = UTIME_NOW;
595 } else
596 times[1].tv_nsec = UTIME_OMIT;
598 ret = utimensat(-1, fid->abs_path, times, AT_SYMLINK_NOFOLLOW);
599 if (ret < 0)
600 goto err_out;
603 * If the only valid entry in iattr is ctime we can call
604 * chown(-1,-1) to update the ctime of the file
606 if ((p9attr.valid & (ATTR_UID | ATTR_GID)) ||
607 ((p9attr.valid & ATTR_CTIME)
608 && !((p9attr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
609 if (!(p9attr.valid & ATTR_UID))
610 p9attr.uid = -1;
612 if (!(p9attr.valid & ATTR_GID))
613 p9attr.gid = -1;
615 ret = lchown(fid->abs_path, p9attr.uid, p9attr.gid);
616 if (ret < 0)
617 goto err_out;
619 if (p9attr.valid & (ATTR_SIZE)) {
620 ret = truncate(fid->abs_path, p9attr.size);
621 if (ret < 0)
622 goto err_out;
624 *outlen = VIRTIO_P9_HDR_LEN;
625 virtio_p9_set_reply_header(pdu, *outlen);
626 return;
627 err_out:
628 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
629 return;
632 static void virtio_p9_write(struct p9_dev *p9dev,
633 struct p9_pdu *pdu, u32 *outlen)
636 u64 offset;
637 u32 fid_val;
638 u32 count;
639 ssize_t res;
640 u16 iov_cnt;
641 void *iov_base;
642 size_t iov_len;
643 struct p9_fid *fid;
644 /* u32 fid + u64 offset + u32 count */
645 int twrite_size = sizeof(u32) + sizeof(u64) + sizeof(u32);
647 virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
648 fid = &p9dev->fids[fid_val];
650 iov_base = pdu->out_iov[0].iov_base;
651 iov_len = pdu->out_iov[0].iov_len;
652 iov_cnt = pdu->out_iov_cnt;
654 /* Adjust the iovec to skip the header and meta data */
655 pdu->out_iov[0].iov_base += (sizeof(struct p9_msg) + twrite_size);
656 pdu->out_iov[0].iov_len -= (sizeof(struct p9_msg) + twrite_size);
657 pdu->out_iov_cnt = virtio_p9_update_iov_cnt(pdu->out_iov, count,
658 pdu->out_iov_cnt);
659 res = pwritev(fid->fd, pdu->out_iov, pdu->out_iov_cnt, offset);
661 * Update the iov_base back, so that rest of
662 * pdu_readf works correctly.
664 pdu->out_iov[0].iov_base = iov_base;
665 pdu->out_iov[0].iov_len = iov_len;
666 pdu->out_iov_cnt = iov_cnt;
668 if (res < 0)
669 goto err_out;
670 virtio_p9_pdu_writef(pdu, "d", res);
671 *outlen = pdu->write_offset;
672 virtio_p9_set_reply_header(pdu, *outlen);
673 return;
674 err_out:
675 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
676 return;
679 static void virtio_p9_readlink(struct p9_dev *p9dev,
680 struct p9_pdu *pdu, u32 *outlen)
682 int ret;
683 u32 fid_val;
684 struct p9_fid *fid;
685 char target_path[PATH_MAX];
687 virtio_p9_pdu_readf(pdu, "d", &fid_val);
688 fid = &p9dev->fids[fid_val];
690 memset(target_path, 0, PATH_MAX);
691 ret = readlink(fid->abs_path, target_path, PATH_MAX - 1);
692 if (ret < 0)
693 goto err_out;
695 virtio_p9_pdu_writef(pdu, "s", target_path);
696 *outlen = pdu->write_offset;
697 virtio_p9_set_reply_header(pdu, *outlen);
698 return;
699 err_out:
700 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
701 return;
704 static void virtio_p9_statfs(struct p9_dev *p9dev,
705 struct p9_pdu *pdu, u32 *outlen)
707 int ret;
708 u64 fsid;
709 u32 fid_val;
710 struct p9_fid *fid;
711 struct statfs stat_buf;
713 virtio_p9_pdu_readf(pdu, "d", &fid_val);
714 fid = &p9dev->fids[fid_val];
716 ret = statfs(fid->abs_path, &stat_buf);
717 if (ret < 0)
718 goto err_out;
719 /* FIXME!! f_blocks needs update based on client msize */
720 fsid = (unsigned int) stat_buf.f_fsid.__val[0] |
721 (unsigned long long)stat_buf.f_fsid.__val[1] << 32;
722 virtio_p9_pdu_writef(pdu, "ddqqqqqqd", stat_buf.f_type,
723 stat_buf.f_bsize, stat_buf.f_blocks,
724 stat_buf.f_bfree, stat_buf.f_bavail,
725 stat_buf.f_files, stat_buf.f_ffree,
726 fsid, stat_buf.f_namelen);
727 *outlen = pdu->write_offset;
728 virtio_p9_set_reply_header(pdu, *outlen);
729 return;
730 err_out:
731 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
732 return;
735 static void virtio_p9_mknod(struct p9_dev *p9dev,
736 struct p9_pdu *pdu, u32 *outlen)
738 int ret;
739 char *name;
740 struct stat st;
741 struct p9_fid *dfid;
742 struct p9_qid qid;
743 char full_path[PATH_MAX];
744 u32 fid_val, mode, major, minor, gid;
746 virtio_p9_pdu_readf(pdu, "dsdddd", &fid_val, &name, &mode,
747 &major, &minor, &gid);
749 dfid = &p9dev->fids[fid_val];
750 sprintf(full_path, "%s/%s", dfid->abs_path, name);
751 ret = mknod(full_path, mode, makedev(major, minor));
752 if (ret < 0)
753 goto err_out;
755 if (lstat(full_path, &st) < 0)
756 goto err_out;
758 ret = chmod(full_path, mode & 0777);
759 if (ret < 0)
760 goto err_out;
762 ret = lchown(full_path, dfid->uid, gid);
763 if (ret < 0)
764 goto err_out;
766 stat2qid(&st, &qid);
767 virtio_p9_pdu_writef(pdu, "Q", &qid);
768 free(name);
769 *outlen = pdu->write_offset;
770 virtio_p9_set_reply_header(pdu, *outlen);
771 return;
772 err_out:
773 free(name);
774 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
775 return;
778 static void virtio_p9_fsync(struct p9_dev *p9dev,
779 struct p9_pdu *pdu, u32 *outlen)
781 int ret;
782 struct p9_fid *fid;
783 u32 fid_val, datasync;
785 virtio_p9_pdu_readf(pdu, "dd", &fid_val, &datasync);
786 fid = &p9dev->fids[fid_val];
788 if (datasync)
789 ret = fdatasync(fid->fd);
790 else
791 ret = fsync(fid->fd);
792 if (ret < 0)
793 goto err_out;
794 *outlen = pdu->write_offset;
795 virtio_p9_set_reply_header(pdu, *outlen);
796 return;
797 err_out:
798 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
799 return;
802 static void virtio_p9_symlink(struct p9_dev *p9dev,
803 struct p9_pdu *pdu, u32 *outlen)
805 int ret;
806 struct stat st;
807 u32 fid_val, gid;
808 struct p9_qid qid;
809 struct p9_fid *dfid;
810 char new_name[PATH_MAX];
811 char *old_path, *name;
813 virtio_p9_pdu_readf(pdu, "dssd", &fid_val, &name, &old_path, &gid);
815 dfid = &p9dev->fids[fid_val];
816 sprintf(new_name, "%s/%s", dfid->abs_path, name);
817 ret = symlink(old_path, new_name);
818 if (ret < 0)
819 goto err_out;
821 if (lstat(new_name, &st) < 0)
822 goto err_out;
824 ret = lchown(new_name, dfid->uid, gid);
825 if (ret < 0)
826 goto err_out;
828 stat2qid(&st, &qid);
829 virtio_p9_pdu_writef(pdu, "Q", &qid);
830 free(name);
831 free(old_path);
832 *outlen = pdu->write_offset;
833 virtio_p9_set_reply_header(pdu, *outlen);
834 return;
835 err_out:
836 free(name);
837 free(old_path);
838 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
839 return;
842 static void virtio_p9_link(struct p9_dev *p9dev,
843 struct p9_pdu *pdu, u32 *outlen)
845 int ret;
846 char *name;
847 u32 fid_val, dfid_val;
848 struct p9_fid *dfid, *fid;
849 char full_path[PATH_MAX];
851 virtio_p9_pdu_readf(pdu, "dds", &dfid_val, &fid_val, &name);
853 dfid = &p9dev->fids[dfid_val];
854 fid = &p9dev->fids[fid_val];
855 sprintf(full_path, "%s/%s", dfid->abs_path, name);
856 ret = link(fid->abs_path, full_path);
857 if (ret < 0)
858 goto err_out;
859 free(name);
860 *outlen = pdu->write_offset;
861 virtio_p9_set_reply_header(pdu, *outlen);
862 return;
863 err_out:
864 free(name);
865 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
866 return;
870 static void virtio_p9_lock(struct p9_dev *p9dev,
871 struct p9_pdu *pdu, u32 *outlen)
873 u8 ret;
874 u32 fid_val;
875 struct p9_flock flock;
877 virtio_p9_pdu_readf(pdu, "dbdqqds", &fid_val, &flock.type,
878 &flock.flags, &flock.start, &flock.length,
879 &flock.proc_id, &flock.client_id);
881 /* Just return success */
882 ret = P9_LOCK_SUCCESS;
883 virtio_p9_pdu_writef(pdu, "d", ret);
884 *outlen = pdu->write_offset;
885 virtio_p9_set_reply_header(pdu, *outlen);
886 free(flock.client_id);
887 return;
890 static void virtio_p9_getlock(struct p9_dev *p9dev,
891 struct p9_pdu *pdu, u32 *outlen)
893 u32 fid_val;
894 struct p9_getlock glock;
895 virtio_p9_pdu_readf(pdu, "dbqqds", &fid_val, &glock.type,
896 &glock.start, &glock.length, &glock.proc_id,
897 &glock.client_id);
899 /* Just return success */
900 glock.type = F_UNLCK;
901 virtio_p9_pdu_writef(pdu, "bqqds", glock.type,
902 glock.start, glock.length, glock.proc_id,
903 glock.client_id);
904 *outlen = pdu->write_offset;
905 virtio_p9_set_reply_header(pdu, *outlen);
906 free(glock.client_id);
907 return;
910 static int virtio_p9_ancestor(char *path, char *ancestor)
912 int size = strlen(ancestor);
913 if (!strncmp(path, ancestor, size)) {
915 * Now check whether ancestor is a full name or
916 * or directory component and not just part
917 * of a name.
919 if (path[size] == '\0' || path[size] == '/')
920 return 1;
922 return 0;
925 static void virtio_p9_fix_path(char *fid_path, char *old_name, char *new_name)
927 char tmp_name[PATH_MAX];
928 size_t rp_sz = strlen(old_name);
930 if (rp_sz == strlen(fid_path)) {
931 /* replace the full name */
932 strcpy(fid_path, new_name);
933 return;
935 /* save the trailing path details */
936 strcpy(tmp_name, fid_path + rp_sz);
937 sprintf(fid_path, "%s%s", new_name, tmp_name);
938 return;
941 static void virtio_p9_renameat(struct p9_dev *p9dev,
942 struct p9_pdu *pdu, u32 *outlen)
944 int i, ret;
945 char *old_name, *new_name;
946 u32 old_dfid_val, new_dfid_val;
947 struct p9_fid *old_dfid, *new_dfid;
948 char old_full_path[PATH_MAX], new_full_path[PATH_MAX];
951 virtio_p9_pdu_readf(pdu, "dsds", &old_dfid_val, &old_name,
952 &new_dfid_val, &new_name);
954 old_dfid = &p9dev->fids[old_dfid_val];
955 new_dfid = &p9dev->fids[new_dfid_val];
957 sprintf(old_full_path, "%s/%s", old_dfid->abs_path, old_name);
958 sprintf(new_full_path, "%s/%s", new_dfid->abs_path, new_name);
959 ret = rename(old_full_path, new_full_path);
960 if (ret < 0)
961 goto err_out;
963 * Now fix path in other fids, if the renamed path is part of
964 * that.
966 for (i = 0; i < VIRTIO_P9_MAX_FID; i++) {
967 if (p9dev->fids[i].fid != P9_NOFID &&
968 virtio_p9_ancestor(p9dev->fids[i].path, old_name)) {
969 virtio_p9_fix_path(p9dev->fids[i].path, old_name,
970 new_name);
973 free(old_name);
974 free(new_name);
975 *outlen = pdu->write_offset;
976 virtio_p9_set_reply_header(pdu, *outlen);
977 return;
978 err_out:
979 free(old_name);
980 free(new_name);
981 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
982 return;
985 static void virtio_p9_unlinkat(struct p9_dev *p9dev,
986 struct p9_pdu *pdu, u32 *outlen)
988 int ret;
989 char *name;
990 u32 fid_val, flags;
991 struct p9_fid *fid;
992 char full_path[PATH_MAX];
994 virtio_p9_pdu_readf(pdu, "dsd", &fid_val, &name, &flags);
995 fid = &p9dev->fids[fid_val];
997 sprintf(full_path, "%s/%s", fid->abs_path, name);
998 ret = remove(full_path);
999 if (ret < 0)
1000 goto err_out;
1001 free(name);
1002 *outlen = pdu->write_offset;
1003 virtio_p9_set_reply_header(pdu, *outlen);
1004 return;
1005 err_out:
1006 free(name);
1007 virtio_p9_error_reply(p9dev, pdu, errno, outlen);
1008 return;
1011 static void virtio_p9_eopnotsupp(struct p9_dev *p9dev,
1012 struct p9_pdu *pdu, u32 *outlen)
1014 return virtio_p9_error_reply(p9dev, pdu, EOPNOTSUPP, outlen);
1017 typedef void p9_handler(struct p9_dev *p9dev,
1018 struct p9_pdu *pdu, u32 *outlen);
1020 /* FIXME should be removed when merging with latest linus tree */
1021 #define P9_TRENAMEAT 74
1022 #define P9_TUNLINKAT 76
1024 static p9_handler *virtio_9p_dotl_handler [] = {
1025 [P9_TREADDIR] = virtio_p9_readdir,
1026 [P9_TSTATFS] = virtio_p9_statfs,
1027 [P9_TGETATTR] = virtio_p9_getattr,
1028 [P9_TSETATTR] = virtio_p9_setattr,
1029 [P9_TXATTRWALK] = virtio_p9_eopnotsupp,
1030 [P9_TXATTRCREATE] = virtio_p9_eopnotsupp,
1031 [P9_TMKNOD] = virtio_p9_mknod,
1032 [P9_TLOCK] = virtio_p9_lock,
1033 [P9_TGETLOCK] = virtio_p9_getlock,
1034 [P9_TRENAMEAT] = virtio_p9_renameat,
1035 [P9_TREADLINK] = virtio_p9_readlink,
1036 [P9_TUNLINKAT] = virtio_p9_unlinkat,
1037 [P9_TMKDIR] = virtio_p9_mkdir,
1038 [P9_TVERSION] = virtio_p9_version,
1039 [P9_TLOPEN] = virtio_p9_open,
1040 [P9_TATTACH] = virtio_p9_attach,
1041 [P9_TWALK] = virtio_p9_walk,
1042 [P9_TCLUNK] = virtio_p9_clunk,
1043 [P9_TFSYNC] = virtio_p9_fsync,
1044 [P9_TREAD] = virtio_p9_read,
1045 [P9_TFLUSH] = virtio_p9_eopnotsupp,
1046 [P9_TLINK] = virtio_p9_link,
1047 [P9_TSYMLINK] = virtio_p9_symlink,
1048 [P9_TLCREATE] = virtio_p9_create,
1049 [P9_TWRITE] = virtio_p9_write,
1052 static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
1054 struct p9_pdu *pdu = calloc(1, sizeof(*pdu));
1055 if (!pdu)
1056 return NULL;
1058 /* skip the pdu header p9_msg */
1059 pdu->read_offset = VIRTIO_P9_HDR_LEN;
1060 pdu->write_offset = VIRTIO_P9_HDR_LEN;
1061 pdu->queue_head = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
1062 pdu->out_iov,
1063 &pdu->in_iov_cnt,
1064 &pdu->out_iov_cnt);
1065 return pdu;
1068 static u8 virtio_p9_get_cmd(struct p9_pdu *pdu)
1070 struct p9_msg *msg;
1072 * we can peek directly into pdu for a u8
1073 * value. The host endianess won't be an issue
1075 msg = pdu->out_iov[0].iov_base;
1076 return msg->cmd;
1079 static bool virtio_p9_do_io_request(struct kvm *kvm, struct p9_dev_job *job)
1081 u8 cmd;
1082 u32 len = 0;
1083 p9_handler *handler;
1084 struct p9_dev *p9dev;
1085 struct virt_queue *vq;
1086 struct p9_pdu *p9pdu;
1088 vq = job->vq;
1089 p9dev = job->p9dev;
1091 p9pdu = virtio_p9_pdu_init(kvm, vq);
1092 cmd = virtio_p9_get_cmd(p9pdu);
1094 if ((cmd >= ARRAY_SIZE(virtio_9p_dotl_handler)) ||
1095 !virtio_9p_dotl_handler[cmd])
1096 handler = virtio_p9_eopnotsupp;
1097 else
1098 handler = virtio_9p_dotl_handler[cmd];
1100 handler(p9dev, p9pdu, &len);
1101 virt_queue__set_used_elem(vq, p9pdu->queue_head, len);
1102 free(p9pdu);
1103 return true;
1106 static void virtio_p9_do_io(struct kvm *kvm, void *param)
1108 struct p9_dev_job *job = (struct p9_dev_job *)param;
1109 struct p9_dev *p9dev = job->p9dev;
1110 struct virt_queue *vq = job->vq;
1112 while (virt_queue__available(vq)) {
1113 virtio_p9_do_io_request(kvm, job);
1114 virtio_pci__signal_vq(kvm, &p9dev->vpci, vq - p9dev->vqs);
1118 static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
1120 struct p9_dev *p9dev = dev;
1122 ((u8 *)(p9dev->config))[offset] = data;
1125 static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
1127 struct p9_dev *p9dev = dev;
1129 return ((u8 *)(p9dev->config))[offset];
1132 static u32 get_host_features(struct kvm *kvm, void *dev)
1134 return 1 << VIRTIO_9P_MOUNT_TAG;
1137 static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
1139 struct p9_dev *p9dev = dev;
1141 p9dev->features = features;
1144 static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
1146 struct p9_dev *p9dev = dev;
1147 struct p9_dev_job *job;
1148 struct virt_queue *queue;
1149 void *p;
1151 compat__remove_message(p9dev->compat_id);
1153 queue = &p9dev->vqs[vq];
1154 queue->pfn = pfn;
1155 p = guest_pfn_to_host(kvm, queue->pfn);
1156 job = &p9dev->jobs[vq];
1158 vring_init(&queue->vring, VIRTQUEUE_NUM, p, VIRTIO_PCI_VRING_ALIGN);
1160 *job = (struct p9_dev_job) {
1161 .vq = queue,
1162 .p9dev = p9dev,
1164 thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
1166 return 0;
1169 static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
1171 struct p9_dev *p9dev = dev;
1173 thread_pool__do_job(&p9dev->jobs[vq].job_id);
1175 return 0;
1178 static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
1180 struct p9_dev *p9dev = dev;
1182 return p9dev->vqs[vq].pfn;
1185 static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
1187 return VIRTQUEUE_NUM;
1190 int virtio_9p__init(struct kvm *kvm)
1192 struct p9_dev *p9dev;
1194 list_for_each_entry(p9dev, &devs, list) {
1195 virtio_pci__init(kvm, &p9dev->vpci, p9dev, PCI_DEVICE_ID_VIRTIO_P9, VIRTIO_ID_9P);
1196 p9dev->vpci.ops = (struct virtio_pci_ops) {
1197 .set_config = set_config,
1198 .get_config = get_config,
1199 .get_host_features = get_host_features,
1200 .set_guest_features = set_guest_features,
1201 .init_vq = init_vq,
1202 .notify_vq = notify_vq,
1203 .get_pfn_vq = get_pfn_vq,
1204 .get_size_vq = get_size_vq,
1208 return 0;
1211 int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name)
1213 struct p9_dev *p9dev;
1214 u32 i, root_len;
1215 int err = 0;
1217 p9dev = calloc(1, sizeof(*p9dev));
1218 if (!p9dev)
1219 return -ENOMEM;
1221 if (!tag_name)
1222 tag_name = VIRTIO_P9_DEFAULT_TAG;
1224 p9dev->config = calloc(1, sizeof(*p9dev->config) + strlen(tag_name) + 1);
1225 if (p9dev->config == NULL) {
1226 err = -ENOMEM;
1227 goto free_p9dev;
1230 strcpy(p9dev->root_dir, root);
1231 root_len = strlen(root);
1233 * We prefix the full path in all fids, This allows us to get the
1234 * absolute path of an fid without playing with strings.
1236 for (i = 0; i < VIRTIO_P9_MAX_FID; i++) {
1237 strcpy(p9dev->fids[i].abs_path, root);
1238 p9dev->fids[i].path = p9dev->fids[i].abs_path + root_len;
1240 p9dev->config->tag_len = strlen(tag_name);
1241 if (p9dev->config->tag_len > MAX_TAG_LEN) {
1242 err = -EINVAL;
1243 goto free_p9dev_config;
1246 memcpy(&p9dev->config->tag, tag_name, strlen(tag_name));
1248 list_add(&p9dev->list, &devs);
1250 p9dev->compat_id = compat__add_message("virtio-9p device was not detected",
1251 "While you have requested a virtio-9p device, "
1252 "the guest kernel didn't seem to detect it.\n"
1253 "Please make sure that the kernel was compiled"
1254 "with CONFIG_NET_9P_VIRTIO.");
1256 return err;
1258 free_p9dev_config:
1259 free(p9dev->config);
1260 free_p9dev:
1261 free(p9dev);
1262 return err;