From patchwork Mon Aug 1 14:08:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 1026072 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p71E9Qdg026956 for ; Mon, 1 Aug 2011 14:09:26 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752065Ab1HAOJY (ORCPT ); Mon, 1 Aug 2011 10:09:24 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:47747 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751949Ab1HAOJX (ORCPT ); Mon, 1 Aug 2011 10:09:23 -0400 Received: by wwe5 with SMTP id 5so5672601wwe.1 for ; Mon, 01 Aug 2011 07:09:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; bh=JMR4nWGcZpQvPn3/oCx8h1O25TXLZHF1EvgDiWuwevY=; b=W56aQ3Msm1kIqjZITOY6ffQ0O+SvaYmxaO7culCG/H0XmIDsYNHTHwqTDE7+fNYH8V EKVM15qQsXDeO/jG6iuWIFc1e2aVRcTR1GG5kicYQ62+m1ZLxkXNLHe98UoIokRX0aoG lzzKE89o3KqqSlL9bJa3MAj5efcXPeOElwVZU= Received: by 10.227.200.210 with SMTP id ex18mr4228400wbb.7.1312207762123; Mon, 01 Aug 2011 07:09:22 -0700 (PDT) Received: from localhost.localdomain ([31.210.177.112]) by mx.google.com with ESMTPS id fp3sm4207659wbb.47.2011.08.01.07.09.18 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 01 Aug 2011 07:09:21 -0700 (PDT) From: Sasha Levin To: penberg@kernel.org Cc: kvm@vger.kernel.org, aneesh.kumar@linux.vnet.ibm.com, mingo@elte.hu, asias.hejun@gmail.com, gorcunov@gmail.com, Sasha Levin Subject: [PATCH 1/2] kvm tools: Add support for 9p2000.u Date: Mon, 1 Aug 2011 17:08:22 +0300 Message-Id: <1312207703-16947-1-git-send-email-levinsasha928@gmail.com> X-Mailer: git-send-email 1.7.6 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Mon, 01 Aug 2011 14:09:26 +0000 (UTC) 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 --- tools/kvm/include/kvm/virtio-9p.h | 4 +- tools/kvm/virtio/9p-pdu.c | 6 ++- tools/kvm/virtio/9p.c | 75 +++++++++++++++++++++++++++++++------ 3 files changed, 69 insertions(+), 16 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..a6eafe0 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,30 @@ 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) { + int r; + + r = symlink(ext, full_path); + if (r < 0) + goto err_out; + fd = open(full_path, omode2uflags(mode)); + if (fd < 0) + goto err_out; + close_fid(p9dev, fid_val); + fid->fd = fd; + } else if (perm & P9_DMLINK) { + int r; + int ext_fid = atoi(ext); + + r = link(p9dev->fids[ext_fid].abs_path, full_path); + if (r < 0) + goto err_out; + + fd = open(full_path, omode2uflags(mode)); + if (fd < 0) + goto err_out; + close_fid(p9dev, fid_val); + fid->fd = fd; } else { fd = open(full_path, omode2uflags(mode) | O_CREAT, 0777); if (fd < 0) @@ -294,7 +318,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,8 +339,10 @@ 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) + if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0) { + ret = ENOENT; goto err_out; + } st2qid(&st, &wqid); new_fid->is_dir = S_ISDIR(st.st_mode); @@ -340,7 +366,7 @@ static void virtio_p9_walk(struct p9_dev *p9dev, virtio_p9_set_reply_header(pdu, *outlen); return; err_out: - virtio_p9_error_reply(p9dev, pdu, errno, outlen); + virtio_p9_error_reply(p9dev, pdu, ret, outlen); return; } @@ -381,6 +407,12 @@ err_out: 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 +425,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 +444,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 +489,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 +536,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: