X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnfsd%2Fnfs4xdr.c;h=e95b02a70ba96cb66031c6340cb82055dbfaad6f;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=1634701eb9d376eade697741299cf463e9e0d70a;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 1634701eb..e95b02a70 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -288,27 +288,40 @@ u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) return p; } -char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) +static int +defer_free(struct nfsd4_compoundargs *argp, + void (*release)(const void *), void *p) { struct tmpbuf *tb; + + tb = kmalloc(sizeof(*tb), GFP_KERNEL); + if (!tb) + return -ENOMEM; + tb->buf = p; + tb->release = release; + tb->next = argp->to_free; + argp->to_free = tb; + return 0; +} + +char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) +{ + void *new = NULL; if (p == argp->tmp) { - p = kmalloc(nbytes, GFP_KERNEL); - if (!p) return NULL; + new = kmalloc(nbytes, GFP_KERNEL); + if (!new) return NULL; + p = new; memcpy(p, argp->tmp, nbytes); } else { if (p != argp->tmpp) BUG(); argp->tmpp = NULL; } - tb = kmalloc(sizeof(*tb), GFP_KERNEL); - if (!tb) { - kfree(p); + if (defer_free(argp, kfree, p)) { + kfree(new); return NULL; - } - tb->buf = p; - tb->next = argp->to_free; - argp->to_free = tb; - return (char*)p; + } else + return (char *)p; } @@ -1289,18 +1302,11 @@ static u32 nfs4_ftypes[16] = { NF4SOCK, NF4BAD, NF4LNK, NF4BAD, }; -static inline int -xdr_padding(int l) -{ - return 3 - ((l - 1) & 3); /* smallest i>=0 such that (l+i)%4 = 0 */ -} - static int nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id, u32 **p, int *buflen) { int status; - u32 len; if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4) return nfserr_resource; @@ -1310,11 +1316,8 @@ nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id, status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1)); if (status < 0) return nfserrno(status); - len = (unsigned)status; - *(*p)++ = htonl(len); - memset((u8 *)*p + len, 0, xdr_padding(len)); - *p += XDR_QUADLEN(len); - *buflen -= (XDR_QUADLEN(len) << 2) + 4; + *p = xdr_encode_opaque(*p, NULL, status); + *buflen -= (XDR_QUADLEN(status) << 2) + 4; BUG_ON(*buflen < 0); return 0; } @@ -1559,7 +1562,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, } if (bmval1 & FATTR4_WORD1_OWNER) { status = nfsd4_encode_user(rqstp, - XIDINO_UID(stat.uid, stat.xid), &p, &buflen); + XIDINO_UID(XID_TAG(dentry->d_inode), + stat.uid, stat.xid), &p, &buflen); if (status == nfserr_resource) goto out_resource; if (status) @@ -1567,7 +1571,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, } if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { status = nfsd4_encode_group(rqstp, - XIDINO_GID(stat.gid, stat.xid), &p, &buflen); + XIDINO_GID(XID_TAG(dentry->d_inode), + stat.gid, stat.xid), &p, &buflen); if (status == nfserr_resource) goto out_resource; if (status) @@ -2474,6 +2479,24 @@ nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy) return xdr_ressize_check(rqstp, p); } +void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) +{ + if (args->ops != args->iops) { + kfree(args->ops); + args->ops = args->iops; + } + if (args->tmpp) { + kfree(args->tmpp); + args->tmpp = NULL; + } + while (args->to_free) { + struct tmpbuf *tb = args->to_free; + args->to_free = tb->next; + tb->release(tb->buf); + kfree(tb); + } +} + int nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args) { @@ -2490,20 +2513,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoun status = nfsd4_decode_compound(args); if (status) { - if (args->ops != args->iops) { - kfree(args->ops); - args->ops = args->iops; - } - if (args->tmpp) { - kfree(args->tmpp); - args->tmpp = NULL; - } - while (args->to_free) { - struct tmpbuf *tb = args->to_free; - args->to_free = tb->next; - kfree(tb->buf); - kfree(tb); - } + nfsd4_release_compoundargs(args); } return !status; } @@ -2514,7 +2524,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compound /* * All that remains is to write the tag and operation count... */ - struct iovec *iov; + struct kvec *iov; p = resp->tagp; *p++ = htonl(resp->taglen); memcpy(p, resp->tag, resp->taglen);