1 #include "kvm/virtio-pci-dev.h"
2 #include "kvm/ioport.h"
4 #include "kvm/threadpool.h"
6 #include "kvm/virtio-9p.h"
7 #include "kvm/guest_compat.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
);
33 static void stat2qid(struct stat
*st
, struct p9_qid
*qid
)
35 *qid
= (struct p9_qid
) {
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
)
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
)
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
);
80 total
+= iov
[i
].iov_len
;
85 static void virtio_p9_error_reply(struct p9_dev
*p9dev
,
86 struct p9_pdu
*pdu
, int err
, u32
*outlen
)
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
)
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
);
116 virtio_p9_pdu_writef(pdu
, "ds", msize
, "unknown");
118 *outlen
= pdu
->write_offset
;
119 virtio_p9_set_reply_header(pdu
, *outlen
);
124 static void virtio_p9_clunk(struct p9_dev
*p9dev
,
125 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
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
);
148 static void virtio_p9_open(struct p9_dev
*p9dev
,
149 struct p9_pdu
*pdu
, u32
*outlen
)
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)
165 if (new_fid
->is_dir
) {
166 new_fid
->dir
= opendir(new_fid
->abs_path
);
170 new_fid
->fd
= open(new_fid
->abs_path
,
171 virtio_p9_openflags(flags
));
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
);
182 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
186 static void virtio_p9_create(struct p9_dev
*p9dev
,
187 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
207 close_fid(p9dev
, dfid_val
);
210 if (lstat(full_path
, &st
) < 0)
213 ret
= chmod(full_path
, mode
& 0777);
217 ret
= lchown(full_path
, dfid
->uid
, gid
);
221 sprintf(dfid
->path
, "%s/%s", dfid
->path
, name
);
223 virtio_p9_pdu_writef(pdu
, "Qd", &qid
, 0);
224 *outlen
= pdu
->write_offset
;
225 virtio_p9_set_reply_header(pdu
, *outlen
);
230 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
234 static void virtio_p9_mkdir(struct p9_dev
*p9dev
,
235 struct p9_pdu
*pdu
, u32
*outlen
)
242 char full_path
[PATH_MAX
];
243 u32 dfid_val
, mode
, gid
;
245 virtio_p9_pdu_readf(pdu
, "dsdd", &dfid_val
,
247 dfid
= &p9dev
->fids
[dfid_val
];
249 sprintf(full_path
, "%s/%s", dfid
->abs_path
, name
);
250 ret
= mkdir(full_path
, mode
);
254 if (lstat(full_path
, &st
) < 0)
257 ret
= chmod(full_path
, mode
& 0777);
261 ret
= lchown(full_path
, dfid
->uid
, gid
);
266 virtio_p9_pdu_writef(pdu
, "Qd", &qid
, 0);
267 *outlen
= pdu
->write_offset
;
268 virtio_p9_set_reply_header(pdu
, *outlen
);
273 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
277 static void virtio_p9_walk(struct p9_dev
*p9dev
,
278 struct p9_pdu
*pdu
, u32
*outlen
)
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
];
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
++) {
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)
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
;
317 virtio_p9_pdu_writef(pdu
, "Q", &wqid
);
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
);
335 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
339 static void virtio_p9_attach(struct p9_dev
*p9dev
,
340 struct p9_pdu
*pdu
, u32
*outlen
)
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)
362 fid
= &p9dev
->fids
[fid_val
];
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
);
373 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
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
)
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
,
424 rcount
= preadv(fid
->fd
, pdu
->in_iov
,
425 pdu
->in_iov_cnt
, offset
);
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
);
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
)
460 char full_path
[PATH_MAX
];
461 u64 offset
, old_offset
;
464 virtio_p9_pdu_readf(pdu
, "dqd", &fid_val
, &offset
, &count
);
465 fid
= &p9dev
->fids
[fid_val
];
472 /* Move the offset specified */
473 seekdir(fid
->dir
, 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
);
485 if ((rcount
+ virtio_p9_dentry_size(dent
)) > count
) {
486 /* seek to the previous offset and return */
487 seekdir(fid
->dir
, old_offset
);
490 old_offset
= dent
->d_off
;
491 lstat(rel_to_abs(p9dev
, dent
->d_name
, full_path
), &st
);
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
);
506 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
511 static void virtio_p9_getattr(struct p9_dev
*p9dev
,
512 struct p9_pdu
*pdu
, u32
*outlen
)
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)
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
);
531 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
535 /* FIXME!! from linux/fs.h */
537 * Attribute flags. These should be or-ed together to figure out what
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
)
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
);
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
;
583 times
[0].tv_nsec
= UTIME_NOW
;
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
;
593 times
[1].tv_nsec
= UTIME_NOW
;
596 times
[1].tv_nsec
= UTIME_OMIT
;
598 ret
= utimensat(-1, fid
->abs_path
, times
, AT_SYMLINK_NOFOLLOW
);
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
))
612 if (!(p9attr
.valid
& ATTR_GID
))
615 ret
= lchown(fid
->abs_path
, p9attr
.uid
, p9attr
.gid
);
619 if (p9attr
.valid
& (ATTR_SIZE
)) {
620 ret
= truncate(fid
->abs_path
, p9attr
.size
);
624 *outlen
= VIRTIO_P9_HDR_LEN
;
625 virtio_p9_set_reply_header(pdu
, *outlen
);
628 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
632 static void virtio_p9_write(struct p9_dev
*p9dev
,
633 struct p9_pdu
*pdu
, u32
*outlen
)
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
,
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
;
670 virtio_p9_pdu_writef(pdu
, "d", res
);
671 *outlen
= pdu
->write_offset
;
672 virtio_p9_set_reply_header(pdu
, *outlen
);
675 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
679 static void virtio_p9_readlink(struct p9_dev
*p9dev
,
680 struct p9_pdu
*pdu
, u32
*outlen
)
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);
695 virtio_p9_pdu_writef(pdu
, "s", target_path
);
696 *outlen
= pdu
->write_offset
;
697 virtio_p9_set_reply_header(pdu
, *outlen
);
700 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
704 static void virtio_p9_statfs(struct p9_dev
*p9dev
,
705 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
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
);
731 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
735 static void virtio_p9_mknod(struct p9_dev
*p9dev
,
736 struct p9_pdu
*pdu
, u32
*outlen
)
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
));
755 if (lstat(full_path
, &st
) < 0)
758 ret
= chmod(full_path
, mode
& 0777);
762 ret
= lchown(full_path
, dfid
->uid
, gid
);
767 virtio_p9_pdu_writef(pdu
, "Q", &qid
);
769 *outlen
= pdu
->write_offset
;
770 virtio_p9_set_reply_header(pdu
, *outlen
);
774 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
778 static void virtio_p9_fsync(struct p9_dev
*p9dev
,
779 struct p9_pdu
*pdu
, u32
*outlen
)
783 u32 fid_val
, datasync
;
785 virtio_p9_pdu_readf(pdu
, "dd", &fid_val
, &datasync
);
786 fid
= &p9dev
->fids
[fid_val
];
789 ret
= fdatasync(fid
->fd
);
791 ret
= fsync(fid
->fd
);
794 *outlen
= pdu
->write_offset
;
795 virtio_p9_set_reply_header(pdu
, *outlen
);
798 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
802 static void virtio_p9_symlink(struct p9_dev
*p9dev
,
803 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
821 if (lstat(new_name
, &st
) < 0)
824 ret
= lchown(new_name
, dfid
->uid
, gid
);
829 virtio_p9_pdu_writef(pdu
, "Q", &qid
);
832 *outlen
= pdu
->write_offset
;
833 virtio_p9_set_reply_header(pdu
, *outlen
);
838 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
842 static void virtio_p9_link(struct p9_dev
*p9dev
,
843 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
860 *outlen
= pdu
->write_offset
;
861 virtio_p9_set_reply_header(pdu
, *outlen
);
865 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
870 static void virtio_p9_lock(struct p9_dev
*p9dev
,
871 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
890 static void virtio_p9_getlock(struct p9_dev
*p9dev
,
891 struct p9_pdu
*pdu
, u32
*outlen
)
894 struct p9_getlock glock
;
895 virtio_p9_pdu_readf(pdu
, "dbqqds", &fid_val
, &glock
.type
,
896 &glock
.start
, &glock
.length
, &glock
.proc_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
,
904 *outlen
= pdu
->write_offset
;
905 virtio_p9_set_reply_header(pdu
, *outlen
);
906 free(glock
.client_id
);
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
919 if (path
[size
] == '\0' || path
[size
] == '/')
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
);
935 /* save the trailing path details */
936 strcpy(tmp_name
, fid_path
+ rp_sz
);
937 sprintf(fid_path
, "%s%s", new_name
, tmp_name
);
941 static void virtio_p9_renameat(struct p9_dev
*p9dev
,
942 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
963 * Now fix path in other fids, if the renamed path is part of
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
,
975 *outlen
= pdu
->write_offset
;
976 virtio_p9_set_reply_header(pdu
, *outlen
);
981 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
985 static void virtio_p9_unlinkat(struct p9_dev
*p9dev
,
986 struct p9_pdu
*pdu
, u32
*outlen
)
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
);
1002 *outlen
= pdu
->write_offset
;
1003 virtio_p9_set_reply_header(pdu
, *outlen
);
1007 virtio_p9_error_reply(p9dev
, pdu
, errno
, outlen
);
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
));
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
,
1068 static u8
virtio_p9_get_cmd(struct p9_pdu
*pdu
)
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
;
1079 static bool virtio_p9_do_io_request(struct kvm
*kvm
, struct p9_dev_job
*job
)
1083 p9_handler
*handler
;
1084 struct p9_dev
*p9dev
;
1085 struct virt_queue
*vq
;
1086 struct p9_pdu
*p9pdu
;
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
;
1098 handler
= virtio_9p_dotl_handler
[cmd
];
1100 handler(p9dev
, p9pdu
, &len
);
1101 virt_queue__set_used_elem(vq
, p9pdu
->queue_head
, len
);
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
;
1151 compat__remove_message(p9dev
->compat_id
);
1153 queue
= &p9dev
->vqs
[vq
];
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
) {
1164 thread_pool__init_job(&job
->job_id
, kvm
, virtio_p9_do_io
, job
);
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
);
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
,
1202 .notify_vq
= notify_vq
,
1203 .get_pfn_vq
= get_pfn_vq
,
1204 .get_size_vq
= get_size_vq
,
1211 int virtio_9p__register(struct kvm
*kvm
, const char *root
, const char *tag_name
)
1213 struct p9_dev
*p9dev
;
1217 p9dev
= calloc(1, sizeof(*p9dev
));
1222 tag_name
= VIRTIO_P9_DEFAULT_TAG
;
1224 p9dev
->config
= calloc(1, sizeof(*p9dev
->config
) + strlen(tag_name
) + 1);
1225 if (p9dev
->config
== NULL
) {
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
) {
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.");
1259 free(p9dev
->config
);