From patchwork Fri May 21 07:32:42 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Aneesh Kumar K.V" X-Patchwork-Id: 101312 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o4L7X7bF014332 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 21 May 2010 07:33:45 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-4.v29.ch3.sourceforge.com) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OFMj8-00075B-EE; Fri, 21 May 2010 07:33:02 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.124] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OFMj7-000755-7Z for v9fs-developer@lists.sourceforge.net; Fri, 21 May 2010 07:33:01 +0000 X-ACL-Warn: Received: from e23smtp07.au.ibm.com ([202.81.31.140]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.69) id 1OFMj4-0005nr-D4 for v9fs-developer@lists.sourceforge.net; Fri, 21 May 2010 07:33:01 +0000 Received: from d23relay03.au.ibm.com (d23relay03.au.ibm.com [202.81.31.245]) by e23smtp07.au.ibm.com (8.14.3/8.13.1) with ESMTP id o4L7Wqdl022036 for ; Fri, 21 May 2010 17:32:52 +1000 Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o4L7WpYj1851460 for ; Fri, 21 May 2010 17:32:51 +1000 Received: from d23av01.au.ibm.com (loopback [127.0.0.1]) by d23av01.au.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id o4L7WpiT022464 for ; Fri, 21 May 2010 17:32:51 +1000 Received: from skywalker.in.ibm.com ([9.77.206.20]) by d23av01.au.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id o4L7Wiko022362; Fri, 21 May 2010 17:32:49 +1000 From: "Aneesh Kumar K.V" To: v9fs-developer@lists.sourceforge.net Date: Fri, 21 May 2010 13:02:42 +0530 Message-Id: <1274427162-19072-4-git-send-email-aneesh.kumar@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1.78.g212f0 In-Reply-To: <1274426949-17713-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> References: <1274426949-17713-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> X-Spam-Score: 0.0 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. _SUMMARY_ X-Headers-End: 1OFMj4-0005nr-D4 Subject: [V9fs-developer] [PATCH 3/3] virtio-9p: Implement TXATTRCREATE X-BeenThere: v9fs-developer@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: v9fs-developer-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 21 May 2010 07:33:46 +0000 (UTC) diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h index 167756a..af51ab9 100644 --- a/hw/file-op-9p.h +++ b/hw/file-op-9p.h @@ -57,6 +57,7 @@ typedef struct FileOperations int (*fsync)(FsContext *, int); int (*lgetxattr)(FsContext *, const char *, const char *, void *, size_t); int (*llistxattr)(FsContext *, const char *, void *, size_t); + int (*lsetxattr)(FsContext *, const char *, const char *, void *, size_t, int); void *opaque; } FileOperations; #endif diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c index e28aa5b..0c30a6e 100644 --- a/hw/virtio-9p-local.c +++ b/hw/virtio-9p-local.c @@ -275,6 +275,12 @@ static int local_llistxattr(FsContext *ctx, const char *path, return llistxattr(rpath(ctx, path), value, size); } +static int local_lsetxattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size, int flags) +{ + return lsetxattr(rpath(ctx, path), name, value, size, flags); +} + FileOperations local_ops = { .lstat = local_lstat, .setuid = local_setuid, @@ -306,4 +312,5 @@ FileOperations local_ops = { .fsync = local_fsync, .lgetxattr = local_lgetxattr, .llistxattr = local_llistxattr, + .lsetxattr = local_lsetxattr, }; diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index e800a3f..0c76e07 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -191,6 +191,14 @@ static int v9fs_do_llistxattr(V9fsState *s, V9fsString *path, value, size); } +static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path, + V9fsString *xattr_name, + void *value, size_t size, int flags) +{ + return s->ops->lsetxattr(&s->ctx, path->data, + xattr_name->data, value, size, flags); +} + static void v9fs_string_init(V9fsString *str) { str->data = NULL; @@ -345,8 +353,39 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) return f; } +static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp) +{ + int retval = 0; + + if (fidp->fs.xattr.copied_len == -1) { + /* getxattr/listxattr fid */ + goto free_value; + } + /* + * if this is fid for setxattr. clunk should + * result in setxattr localcall + */ + if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) { + /* clunk after partial write */ + retval = -EINVAL; + goto free_out; + } + retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name, + fidp->fs.xattr.value, + fidp->fs.xattr.len, + fidp->fs.xattr.flags); +free_out: + v9fs_string_free(&fidp->fs.xattr.name); +free_value: + if (fidp->fs.xattr.value) { + qemu_free(fidp->fs.xattr.value); + } + return retval; +} + static int free_fid(V9fsState *s, int32_t fid) { + int retval = 0; V9fsFidState **fidpp, *fidp; for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) { @@ -373,14 +412,12 @@ static int free_fid(V9fsState *s, int32_t fid) } } if (fidp->fid_type == P9_FID_XATTR) { - if (fidp->fs.xattr.value) { - qemu_free(fidp->fs.xattr.value); - } + retval = v9fs_xattr_fid_clunk(s, fidp); } v9fs_string_free(&fidp->path); qemu_free(fidp); - return 0; + return retval; } #define P9_QID_TYPE_DIR 0x80 @@ -1716,6 +1753,48 @@ out: qemu_free(vs); } +static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) +{ + int i, to_copy; + ssize_t err = 0; + int write_count; + int64_t xattr_len; + + xattr_len = vs->fidp->fs.xattr.len; + write_count = xattr_len - vs->off; + if (write_count > vs->count) { + write_count = vs->count; + } else if (write_count < 0) { + /* + * write beyond XATTR value len specified in + * xattrcreate + */ + err = -ENOSPC; + goto out; + } + vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count); + err = vs->offset; + vs->fidp->fs.xattr.copied_len += write_count; + /* + * Now copy the content from sg list + */ + for (i = 0; i < vs->cnt; i++) { + if (write_count > vs->sg[i].iov_len) { + to_copy = vs->sg[i].iov_len; + } else { + to_copy = write_count; + } + memcpy((char *)vs->fidp->fs.xattr.value + vs->off, + vs->sg[i].iov_base, to_copy); + /* updating vs->off since we are not using below */ + vs->off += to_copy; + write_count -= to_copy; + } +out: + complete_pdu(s, vs->pdu, err); + qemu_free(vs); +} + static void v9fs_write(V9fsState *s, V9fsPDU *pdu) { int32_t fid; @@ -1731,7 +1810,7 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu) vs->len = 0; pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count, - vs->sg, &vs->cnt); + vs->sg, &vs->cnt); vs->fidp = lookup_fid(s, fid); if (vs->fidp == NULL) { @@ -1739,11 +1818,21 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu) goto out; } - if (vs->fidp->fs.fd == -1) { - err = -EINVAL; - goto out; + if (vs->fidp->fid_type == P9_FID_FILE) { + if (vs->fidp->fs.fd == -1) { + err = -EINVAL; + goto out; + } + } else if (vs->fidp->fid_type == P9_FID_XATTR) { + /* + * setxattr operation + */ + v9fs_xattr_write(s, vs); + return; + } else { + err = -EINVAL; + goto out; } - err = v9fs_do_lseek(s, vs->fidp->fs.fd, vs->off, SEEK_SET); v9fs_write_post_lseek(s, vs, err); @@ -2428,10 +2517,47 @@ out: qemu_free(vs); } +static void v9fs_xattrcreate(V9fsState *s, V9fsPDU *pdu) +{ + int flags; + int32_t fid; + ssize_t err = 0; + V9fsXattrState *vs; + + vs = qemu_malloc(sizeof(*vs)); + vs->pdu = pdu; + vs->offset = 7; + + pdu_unmarshal(vs->pdu, vs->offset, "dsqd", + &fid, &vs->name, &vs->size, &flags); + + vs->file_fidp = lookup_fid(s, fid); + if (vs->file_fidp == NULL) { + err = -EINVAL; + goto out; + } + + /* Make the file fid point to xattr */ + vs->xattr_fidp = vs->file_fidp; + vs->xattr_fidp->fid_type = P9_FID_XATTR; + vs->xattr_fidp->fs.xattr.copied_len = 0; + vs->xattr_fidp->fs.xattr.len = vs->size; + vs->xattr_fidp->fs.xattr.flags = flags; + v9fs_string_init(&vs->xattr_fidp->fs.xattr.name); + v9fs_string_copy(&vs->xattr_fidp->fs.xattr.name, &vs->name); + vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size); + +out: + complete_pdu(s, vs->pdu, err); + v9fs_string_free(&vs->name); + qemu_free(vs); +} + typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu); static pdu_handler_t *pdu_handlers[] = { [P9_TXATTRWALK] = v9fs_xattrwalk, + [P9_TXATTRCREATE] = v9fs_xattrcreate, [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 8a544bf..1179f62 100644 --- a/hw/virtio-9p.h +++ b/hw/virtio-9p.h @@ -15,6 +15,8 @@ enum { P9_TXATTRWALK = 30, P9_RXATTRWALK, + P9_TXATTRCREATE = 32, + P9_RXATTRCREATE, P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102,