diff options
-rw-r--r-- | hw/virtio-9p-debug.c | 32 | ||||
-rw-r--r-- | hw/virtio-9p.c | 112 | ||||
-rw-r--r-- | hw/virtio-9p.h | 33 |
3 files changed, 177 insertions, 0 deletions
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c index 240bec8985..a880b13aec 100644 --- a/hw/virtio-9p-debug.c +++ b/hw/virtio-9p-debug.c @@ -178,6 +178,30 @@ static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name) fprintf(llogfile, "}"); } +static void pprint_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp, + const char *name) +{ + fprintf(llogfile, "%s={", name); + pprint_qid(pdu, rx, offsetp, "qid"); + pprint_int32(pdu, rx, offsetp, ", st_mode"); + pprint_int64(pdu, rx, offsetp, ", st_nlink"); + pprint_int32(pdu, rx, offsetp, ", st_uid"); + pprint_int32(pdu, rx, offsetp, ", st_gid"); + pprint_int64(pdu, rx, offsetp, ", st_rdev"); + pprint_int64(pdu, rx, offsetp, ", st_size"); + pprint_int64(pdu, rx, offsetp, ", st_blksize"); + pprint_int64(pdu, rx, offsetp, ", st_blocks"); + pprint_int64(pdu, rx, offsetp, ", atime"); + pprint_int64(pdu, rx, offsetp, ", atime_nsec"); + pprint_int64(pdu, rx, offsetp, ", mtime"); + pprint_int64(pdu, rx, offsetp, ", mtime_nsec"); + pprint_int64(pdu, rx, offsetp, ", ctime"); + pprint_int64(pdu, rx, offsetp, ", ctime_nsec"); + fprintf(llogfile, "}"); +} + + + static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name) { int sg_count = get_sg_count(pdu, rx); @@ -353,6 +377,14 @@ void pprint_pdu(V9fsPDU *pdu) pprint_int32(pdu, 1, &offset, "msize"); pprint_str(pdu, 1, &offset, ", version"); break; + case P9_TGETATTR: + fprintf(llogfile, "TGETATTR: ("); + pprint_int32(pdu, 0, &offset, "fid"); + break; + case P9_RGETATTR: + fprintf(llogfile, "RGETATTR: ("); + pprint_stat_dotl(pdu, 1, &offset, "getattr"); + break; case P9_TAUTH: fprintf(llogfile, "TAUTH: ("); pprint_int32(pdu, 0, &offset, "afid"); diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index f6eb0f3075..a8f1735edb 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -736,6 +736,21 @@ static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) statp->n_gid, statp->n_muid); break; } + case 'A': { + V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *); + offset += pdu_marshal(pdu, offset, "qQdddqqqqqqqqqqqqqqq", + statp->st_result_mask, + &statp->qid, statp->st_mode, + statp->st_uid, statp->st_gid, + statp->st_nlink, statp->st_rdev, + statp->st_size, statp->st_blksize, statp->st_blocks, + statp->st_atime_sec, statp->st_atime_nsec, + statp->st_mtime_sec, statp->st_mtime_nsec, + statp->st_ctime_sec, statp->st_ctime_nsec, + statp->st_btime_sec, statp->st_btime_nsec, + statp->st_gen, statp->st_data_version); + break; + } default: break; } @@ -963,6 +978,51 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name, return 0; } +#define P9_STATS_MODE 0x00000001ULL +#define P9_STATS_NLINK 0x00000002ULL +#define P9_STATS_UID 0x00000004ULL +#define P9_STATS_GID 0x00000008ULL +#define P9_STATS_RDEV 0x00000010ULL +#define P9_STATS_ATIME 0x00000020ULL +#define P9_STATS_MTIME 0x00000040ULL +#define P9_STATS_CTIME 0x00000080ULL +#define P9_STATS_INO 0x00000100ULL +#define P9_STATS_SIZE 0x00000200ULL +#define P9_STATS_BLOCKS 0x00000400ULL + +#define P9_STATS_BTIME 0x00000800ULL +#define P9_STATS_GEN 0x00001000ULL +#define P9_STATS_DATA_VERSION 0x00002000ULL + +#define P9_STATS_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */ +#define P9_STATS_ALL 0x00003fffULL /* Mask for All fields above */ + + +static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf, + V9fsStatDotl *v9lstat) +{ + memset(v9lstat, 0, sizeof(*v9lstat)); + + v9lstat->st_mode = stbuf->st_mode; + v9lstat->st_nlink = stbuf->st_nlink; + v9lstat->st_uid = stbuf->st_uid; + v9lstat->st_gid = stbuf->st_gid; + v9lstat->st_rdev = stbuf->st_rdev; + v9lstat->st_size = stbuf->st_size; + v9lstat->st_blksize = stbuf->st_blksize; + v9lstat->st_blocks = stbuf->st_blocks; + v9lstat->st_atime_sec = stbuf->st_atime; + v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec; + v9lstat->st_mtime_sec = stbuf->st_mtime; + v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec; + v9lstat->st_ctime_sec = stbuf->st_ctime; + v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec; + /* Currently we only support BASIC fields in stat */ + v9lstat->st_result_mask = P9_STATS_BASIC; + + stat_to_qid(stbuf, &v9lstat->qid); +} + static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt) { while (len && *iovcnt) { @@ -1129,6 +1189,57 @@ out: qemu_free(vs); } +static void v9fs_getattr_post_lstat(V9fsState *s, V9fsStatStateDotl *vs, + int err) +{ + if (err == -1) { + err = -errno; + goto out; + } + + stat_to_v9stat_dotl(s, &vs->stbuf, &vs->v9stat_dotl); + vs->offset += pdu_marshal(vs->pdu, vs->offset, "A", &vs->v9stat_dotl); + err = vs->offset; + +out: + complete_pdu(s, vs->pdu, err); + qemu_free(vs); +} + +static void v9fs_getattr(V9fsState *s, V9fsPDU *pdu) +{ + int32_t fid; + V9fsStatStateDotl *vs; + ssize_t err = 0; + V9fsFidState *fidp; + uint64_t request_mask; + + vs = qemu_malloc(sizeof(*vs)); + vs->pdu = pdu; + vs->offset = 7; + + memset(&vs->v9stat_dotl, 0, sizeof(vs->v9stat_dotl)); + + pdu_unmarshal(vs->pdu, vs->offset, "dq", &fid, &request_mask); + + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + err = -ENOENT; + goto out; + } + + /* Currently we only support BASIC fields in stat, so there is no + * need to look at request_mask. + */ + err = v9fs_do_lstat(s, &fidp->path, &vs->stbuf); + v9fs_getattr_post_lstat(s, vs, err); + return; + +out: + complete_pdu(s, vs->pdu, err); + qemu_free(vs); +} + static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err) { complete_pdu(s, vs->pdu, err); @@ -2391,6 +2502,7 @@ typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu); static pdu_handler_t *pdu_handlers[] = { [P9_TREADDIR] = v9fs_readdir, [P9_TSTATFS] = v9fs_statfs, + [P9_TGETATTR] = v9fs_getattr, [P9_TVERSION] = v9fs_version, [P9_TATTACH] = v9fs_attach, [P9_TSTAT] = v9fs_stat, diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h index 4ee38302b7..1feed82a09 100644 --- a/hw/virtio-9p.h +++ b/hw/virtio-9p.h @@ -15,6 +15,8 @@ enum { P9_TSTATFS = 8, P9_RSTATFS, + P9_TGETATTR = 24, + P9_RGETATTR, P9_TREADDIR = 40, P9_RREADDIR, P9_TVERSION = 100, @@ -185,6 +187,37 @@ typedef struct V9fsStatState { struct stat stbuf; } V9fsStatState; +typedef struct V9fsStatDotl { + uint64_t st_result_mask; + V9fsQID qid; + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_nlink; + uint64_t st_rdev; + uint64_t st_size; + uint64_t st_blksize; + uint64_t st_blocks; + uint64_t st_atime_sec; + uint64_t st_atime_nsec; + uint64_t st_mtime_sec; + uint64_t st_mtime_nsec; + uint64_t st_ctime_sec; + uint64_t st_ctime_nsec; + uint64_t st_btime_sec; + uint64_t st_btime_nsec; + uint64_t st_gen; + uint64_t st_data_version; +} V9fsStatDotl; + +typedef struct V9fsStatStateDotl { + V9fsPDU *pdu; + size_t offset; + V9fsStatDotl v9stat_dotl; + struct stat stbuf; +} V9fsStatStateDotl; + + typedef struct V9fsWalkState { V9fsPDU *pdu; size_t offset; |