On Tue, 2 Aug 2011 21:46:28 +0300, Sasha Levin <levinsasha928@xxxxxxxxx> wrote: > This patch adds support for the UNIX extensions to 9p2000. > > Supporting thses extensions allow us to transperantly mount UNIX directories > without missing features such as symlinks. > > Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx> > --- > tools/kvm/include/kvm/virtio-9p.h | 4 +- > tools/kvm/virtio/9p-pdu.c | 6 ++- > tools/kvm/virtio/9p.c | 66 ++++++++++++++++++++++++++++++------ > 3 files changed, 61 insertions(+), 15 deletions(-) > > diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h > index 8584f49..0e55e5c 100644 > --- a/tools/kvm/include/kvm/virtio-9p.h > +++ b/tools/kvm/include/kvm/virtio-9p.h > @@ -11,8 +11,8 @@ > #define VIRTQUEUE_NUM 128 > #define VIRTIO_P9_DEFAULT_TAG "kvm_9p" > #define VIRTIO_P9_HDR_LEN (sizeof(u32)+sizeof(u8)+sizeof(u16)) > -#define VIRTIO_P9_MAX_FID 128 > -#define VIRTIO_P9_VERSION "9P2000" > +#define VIRTIO_P9_MAX_FID 256 > +#define VIRTIO_P9_VERSION "9P2000.u" > #define MAX_TAG_LEN 32 > > struct p9_msg { > diff --git a/tools/kvm/virtio/9p-pdu.c b/tools/kvm/virtio/9p-pdu.c > index 0c454db..8ed249f 100644 > --- a/tools/kvm/virtio/9p-pdu.c > +++ b/tools/kvm/virtio/9p-pdu.c > @@ -200,13 +200,15 @@ static int virtio_p9_pdu_encode(struct p9_pdu *pdu, const char *fmt, va_list ap) > case 'S': > { > struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *); > - retval = virtio_p9_pdu_writef(pdu, "wwdQdddqssss", > + retval = virtio_p9_pdu_writef(pdu, "wwdQdddqsssssddd", > stbuf->size, stbuf->type, > stbuf->dev, &stbuf->qid, > stbuf->mode, stbuf->atime, > stbuf->mtime, stbuf->length, > stbuf->name, stbuf->uid, > - stbuf->gid, stbuf->muid); > + stbuf->gid, stbuf->muid, > + stbuf->extension, stbuf->n_uid, > + stbuf->n_gid, stbuf->n_muid); > } > break; > default: > diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c > index 3b5555c..965f873 100644 > --- a/tools/kvm/virtio/9p.c > +++ b/tools/kvm/virtio/9p.c > @@ -162,7 +162,7 @@ static void virtio_p9_error_reply(struct p9_dev *p9dev, > > err_str = strerror(err); > pdu->write_offset = VIRTIO_P9_HDR_LEN; > - virtio_p9_pdu_writef(pdu, "s", err_str); > + virtio_p9_pdu_writef(pdu, "sd", err_str, err); > *outlen = pdu->write_offset; > > pdu->read_offset = sizeof(u32) + sizeof(u8); > @@ -204,7 +204,6 @@ static void virtio_p9_open(struct p9_dev *p9dev, > struct p9_qid qid; > struct p9_fid *new_fid; > > - > virtio_p9_pdu_readf(pdu, "db", &fid, &mode); > new_fid = &p9dev->fids[fid]; > > @@ -242,13 +241,14 @@ static void virtio_p9_create(struct p9_dev *p9dev, > u8 mode; > u32 perm; > char *name; > + char *ext = NULL; > u32 fid_val; > struct stat st; > struct p9_qid qid; > struct p9_fid *fid; > char full_path[PATH_MAX]; > > - virtio_p9_pdu_readf(pdu, "dsdb", &fid_val, &name, &perm, &mode); > + virtio_p9_pdu_readf(pdu, "dsdbs", &fid_val, &name, &perm, &mode, &ext); > fid = &p9dev->fids[fid_val]; > > sprintf(full_path, "%s/%s", fid->abs_path, name); > @@ -262,6 +262,14 @@ static void virtio_p9_create(struct p9_dev *p9dev, > close_fid(p9dev, fid_val); > fid->dir = dir; > fid->is_dir = 1; > + } else if (perm & P9_DMSYMLINK) { > + if (symlink(ext, full_path) < 0) > + goto err_out; > + } else if (perm & P9_DMLINK) { > + int ext_fid = atoi(ext); > + > + if (link(p9dev->fids[ext_fid].abs_path, full_path) < 0) > + goto err_out; > } else { > fd = open(full_path, omode2uflags(mode) | O_CREAT, 0777); > if (fd < 0) > @@ -277,9 +285,14 @@ static void virtio_p9_create(struct p9_dev *p9dev, > virtio_p9_pdu_writef(pdu, "Qd", &qid, 0); > *outlen = pdu->write_offset; > virtio_p9_set_reply_header(pdu, *outlen); > + > + free(name); > + free(ext); > return; > err_out: > virtio_p9_error_reply(p9dev, pdu, errno, outlen); > + free(name); > + free(ext); > return; > } > > @@ -294,7 +307,7 @@ static void virtio_p9_walk(struct p9_dev *p9dev, > u32 newfid_val; > struct p9_qid wqid; > struct p9_fid *new_fid; > - > + int ret; > > virtio_p9_pdu_readf(pdu, "ddw", &fid_val, &newfid_val, &nwname); > new_fid = &p9dev->fids[newfid_val]; > @@ -315,7 +328,9 @@ static void virtio_p9_walk(struct p9_dev *p9dev, > /* Format the new path we're 'walk'ing into */ > sprintf(tmp, "%s/%.*s", > fid->path, (int)strlen(str), str); > - if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0) > + > + ret = lstat(rel_to_abs(p9dev, tmp, full_path), &st); > + if (ret < 0) > goto err_out; > > st2qid(&st, &wqid); > @@ -375,12 +390,22 @@ static void virtio_p9_attach(struct p9_dev *p9dev, > virtio_p9_pdu_writef(pdu, "Q", &qid); > *outlen = pdu->write_offset; > virtio_p9_set_reply_header(pdu, *outlen); > + free(uname); > + free(aname); > return; > err_out: > + free(uname); > + free(aname); > virtio_p9_error_reply(p9dev, pdu, errno, outlen); > return; > } > > +static void virtio_p9_free_stat(struct p9_wstat *wstat) > +{ > + free(wstat->extension); > + free(wstat->name); > +} > + > static void virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name, > struct stat *st, struct p9_wstat *wstat) > { > @@ -393,6 +418,17 @@ static void virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name, > wstat->length = 0; > wstat->mode |= P9_DMDIR; > } > + if (S_ISLNK(st->st_mode)) { > + char tmp[PATH_MAX] = {0}, full_path[PATH_MAX] = {0}; > + > + rel_to_abs(p9dev, name, full_path); > + > + if (readlink(full_path, tmp, PATH_MAX) > 0) > + wstat->extension = strdup(tmp); > + wstat->mode |= P9_DMSYMLINK; > + } else { > + wstat->extension = NULL; > + } > > wstat->atime = st->st_atime; > wstat->mtime = st->st_mtime; > @@ -401,14 +437,20 @@ static void virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name, > wstat->uid = NULL; > wstat->gid = NULL; > wstat->muid = NULL; > + wstat->n_uid = wstat->n_gid = wstat->n_muid = 0; > > - /* NOTE: size shouldn't include its own length */ > - /* size[2] type[2] dev[4] qid[13] */ > - /* mode[4] atime[4] mtime[4] length[8]*/ > - /* name[s] uid[s] gid[s] muid[s] */ > - wstat->size = 2+4+13+4+4+4+8+2+2+2+2; > + /* > + * NOTE: size shouldn't include its own length > + * size[2] type[2] dev[4] qid[13] > + * mode[4] atime[4] mtime[4] length[8] > + * name[s] uid[s] gid[s] muid[s] > + * ext[s] uid[4] gid[4] muid[4] > + */ > + wstat->size = 2+4+13+4+4+4+8+2+2+2+2+2+4+4+4; > if (wstat->name) > wstat->size += strlen(wstat->name); > + if (wstat->extension) > + wstat->size += strlen(wstat->extension); > } > > static void virtio_p9_read(struct p9_dev *p9dev, > @@ -440,6 +482,7 @@ static void virtio_p9_read(struct p9_dev *p9dev, > read = pdu->write_offset; > virtio_p9_pdu_writef(pdu, "S", &wstat); > rcount += pdu->write_offset - read; > + virtio_p9_free_stat(&wstat); > > cur = readdir(fid->dir); > } > @@ -486,6 +529,7 @@ static void virtio_p9_stat(struct p9_dev *p9dev, > > virtio_p9_pdu_writef(pdu, "wS", 0, &wstat); > *outlen = pdu->write_offset; > + virtio_p9_free_stat(&wstat); > virtio_p9_set_reply_header(pdu, *outlen); > return; > err_out: > -- > 1.7.6 > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html