On Tue,  2 Aug 2011 21:46:28 +0300, Sasha Levin <[email protected]> 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 <[email protected]>

Reviewed-by: Aneesh Kumar K.V <[email protected]>

> ---
>  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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to