From patchwork Tue Jun 1 09:28:48 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: 54161 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9A219B7D2E for ; Tue, 1 Jun 2010 19:36:18 +1000 (EST) Received: from localhost ([127.0.0.1]:58667 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OJNt6-00005s-NZ for incoming@patchwork.ozlabs.org; Tue, 01 Jun 2010 05:35:56 -0400 Received: from [140.186.70.92] (port=37121 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OJNmU-00064j-0Y for qemu-devel@nongnu.org; Tue, 01 Jun 2010 05:29:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OJNmQ-0005K8-83 for qemu-devel@nongnu.org; Tue, 01 Jun 2010 05:29:05 -0400 Received: from e28smtp06.in.ibm.com ([122.248.162.6]:37803) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OJNmP-0005It-27 for qemu-devel@nongnu.org; Tue, 01 Jun 2010 05:29:02 -0400 Received: from d28relay01.in.ibm.com (d28relay01.in.ibm.com [9.184.220.58]) by e28smtp06.in.ibm.com (8.14.4/8.13.1) with ESMTP id o519Stgb025703 for ; Tue, 1 Jun 2010 14:58:55 +0530 Received: from d28av05.in.ibm.com (d28av05.in.ibm.com [9.184.220.67]) by d28relay01.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o519St3R2650240 for ; Tue, 1 Jun 2010 14:58:55 +0530 Received: from d28av05.in.ibm.com (loopback [127.0.0.1]) by d28av05.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o519Ssf6028860 for ; Tue, 1 Jun 2010 19:28:55 +1000 Received: from skywalker.in.ibm.com (K50wks273996wss.in.ibm.com [9.124.35.158]) by d28av05.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id o519SsSP028832; Tue, 1 Jun 2010 19:28:54 +1000 From: "Aneesh Kumar K.V" To: qemu-devel@nongnu.org Date: Tue, 1 Jun 2010 14:58:48 +0530 Message-Id: <1275384529-28757-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1.236.g81fa0 In-Reply-To: <1275384529-28757-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> References: <1275384529-28757-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: ericvh@gmail.com, v9fs-developer@lists.sourceforge.net, aliguori@us.ibm.com, "Aneesh Kumar K.V" Subject: [Qemu-devel] [PATCH 3/4] virtio-9p: Implement TXATTRCREATE X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org TXATTRCREATE: Prepare a fid for setting xattr value on a file system object. size[4] TXATTRCREATE tag[2] fid[4] name[s] attr_size[8] flags[4] size[4] RXATTRWALK tag[2] txattrcreate gets a fid pointing to xattr. This fid can later be used to get set the xattr value. flag value is derived from set Linux setxattr. The manpage says "The flags parameter can be used to refine the semantics of the operation. XATTR_CREATE specifies a pure create, which fails if the named attribute exists already. XATTR_REPLACE specifies a pure replace operation, which fails if the named attribute does not already exist. By default (no flags), the extended attribute will be created if need be, or will simply replace the value if the attribute exists." The actual setxattr operation happens when the fid is clunked. At that point the written byte count and the attr_size specified in TXATTRCREATE should be same otherwise an error will be returned. Signed-off-by: Aneesh Kumar K.V --- hw/file-op-9p.h | 1 + hw/virtio-9p-debug.c | 10 ++++ hw/virtio-9p-local.c | 7 +++ hw/virtio-9p.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++--- hw/virtio-9p.h | 2 + 5 files changed, 156 insertions(+), 9 deletions(-) diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h index d5bab9a..a33fc9c 100644 --- a/hw/file-op-9p.h +++ b/hw/file-op-9p.h @@ -77,6 +77,7 @@ typedef struct FileOperations int (*statfs)(FsContext *s, const char *path, struct statfs *stbuf); 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-debug.c b/hw/virtio-9p-debug.c index 5be1670..0916a07 100644 --- a/hw/virtio-9p-debug.c +++ b/hw/virtio-9p-debug.c @@ -550,6 +550,16 @@ void pprint_pdu(V9fsPDU *pdu) fprintf(llogfile, "RXATTRWALK: ("); pprint_int64(pdu, 1, &offset, "xattrsize"); break; + case P9_TXATTRCREATE: + fprintf(llogfile, "TXATTRCREATE: ("); + pprint_int32(pdu, 0, &offset, "fid"); + pprint_str(pdu, 0, &offset, ", name"); + pprint_int64(pdu, 0, &offset, ", xattrsize"); + pprint_int32(pdu, 0, &offset, ", flags"); + break; + case P9_RXATTRCREATE: + fprintf(llogfile, "RXATTRCREATE: ("); + break; default: fprintf(llogfile, "unknown(%d): (", pdu->id); break; diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c index 97b1544..4799fa9 100644 --- a/hw/virtio-9p-local.c +++ b/hw/virtio-9p-local.c @@ -484,6 +484,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, .readlink = local_readlink, @@ -514,4 +520,5 @@ FileOperations local_ops = { .statfs = local_statfs, .lgetxattr = local_lgetxattr, .llistxattr = local_llistxattr, + .lsetxattr = local_lsetxattr, }; diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index de2ec41..7330df0 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -285,6 +285,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; @@ -438,8 +446,41 @@ 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); + if (retval < 0) + retval = -errno; +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) { @@ -466,14 +507,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 @@ -1895,6 +1934,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; @@ -1910,7 +1991,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) { @@ -1918,11 +1999,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); @@ -2709,6 +2800,41 @@ 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); @@ -2718,6 +2844,7 @@ static pdu_handler_t *pdu_handlers[] = { [P9_TGETATTR] = v9fs_getattr, [P9_TSYMLINK] = v9fs_symlink, [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 c534923..172eb3d 100644 --- a/hw/virtio-9p.h +++ b/hw/virtio-9p.h @@ -21,6 +21,8 @@ enum { P9_RGETATTR, P9_TXATTRWALK = 30, P9_RXATTRWALK, + P9_TXATTRCREATE = 32, + P9_RXATTRCREATE, P9_TREADDIR = 40, P9_RREADDIR, P9_TLINK = 70,