#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/nfsd_idmap.h>
+#include <linux/vserver/xid.h>
#define NFSDDBG_FACILITY NFSDDBG_XDR
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;
}
case NF4SOCK:
case NF4FIFO:
case NF4DIR:
- break;
default:
- goto xdr_error;
+ break;
}
READ_BUF(4);
NF4SOCK, NF4BAD, NF4LNK, NF4BAD,
};
+static int
+nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id,
+ u32 **p, int *buflen)
+{
+ int status;
+
+ if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
+ return nfserr_resource;
+ if (group)
+ status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
+ else
+ status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
+ if (status < 0)
+ return nfserrno(status);
+ *p = xdr_encode_opaque(*p, NULL, status);
+ *buflen -= (XDR_QUADLEN(status) << 2) + 4;
+ BUG_ON(*buflen < 0);
+ return 0;
+}
+
+static inline int
+nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
+{
+ return nfsd4_encode_name(rqstp, uid, 0, p, buflen);
+}
+
+static inline int
+nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
+{
+ return nfsd4_encode_name(rqstp, gid, 1, p, buflen);
+}
+
+
/*
* Note: @fhp can be NULL; in this case, we might have to compose the filehandle
* ourselves.
u32 bmval0 = bmval[0];
u32 bmval1 = bmval[1];
struct kstat stat;
- char owner[IDMAP_NAMESZ];
- u32 ownerlen = 0;
- char group[IDMAP_NAMESZ];
- u32 grouplen = 0;
struct svc_fh tempfh;
struct kstatfs statfs;
int buflen = *countp << 2;
goto out;
fhp = &tempfh;
}
- if (bmval1 & FATTR4_WORD1_OWNER) {
- int temp = nfsd_map_uid_to_name(rqstp, stat.uid, owner);
- if (temp < 0) {
- status = temp;
- goto out_nfserr;
- }
- ownerlen = (unsigned) temp;
- }
- if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
- int temp = nfsd_map_gid_to_name(rqstp, stat.gid, group);
- if (temp < 0) {
- status = temp;
- goto out_nfserr;
- }
- grouplen = (unsigned) temp;
- }
-
if ((buflen -= 16) < 0)
goto out_resource;
WRITE32(stat.nlink);
}
if (bmval1 & FATTR4_WORD1_OWNER) {
- buflen -= (XDR_QUADLEN(ownerlen) << 2) + 4;
- if (buflen < 0)
+ status = nfsd4_encode_user(rqstp,
+ XIDINO_UID(XID_TAG(dentry->d_inode),
+ stat.uid, stat.xid), &p, &buflen);
+ if (status == nfserr_resource)
goto out_resource;
- WRITE32(ownerlen);
- WRITEMEM(owner, ownerlen);
+ if (status)
+ goto out;
}
if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
- buflen -= (XDR_QUADLEN(grouplen) << 2) + 4;
- if (buflen < 0)
+ status = nfsd4_encode_group(rqstp,
+ XIDINO_GID(XID_TAG(dentry->d_inode),
+ stat.gid, stat.xid), &p, &buflen);
+ if (status == nfserr_resource)
goto out_resource;
- WRITE32(grouplen);
- WRITEMEM(group, grouplen);
+ if (status)
+ goto out;
}
if (bmval1 & FATTR4_WORD1_RAWDEV) {
if ((buflen -= 8) < 0)
goto error;
}
+ exp_get(exp);
if (d_mountpoint(dentry)) {
if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry,
&exp))) {
* this call will be retried.
*/
dput(dentry);
+ exp_put(exp);
nfserr = nfserr_dropit;
goto error;
}
nfserr = nfsd4_encode_fattr(NULL, exp,
dentry, p, &buflen, cd->rd_bmval,
cd->rd_rqstp);
+ dput(dentry);
+ exp_put(exp);
if (!nfserr) {
p += buflen;
goto out;
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)
{
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;
}
/*
* 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);