#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
case NF4SOCK:
case NF4FIFO:
case NF4DIR:
- break;
default:
- goto xdr_error;
+ break;
}
READ_BUF(4);
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;
+ 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);
+ len = (unsigned)status;
+ *(*p)++ = htonl(len);
+ memset((u8 *)*p + len, 0, xdr_padding(len));
+ *p += XDR_QUADLEN(len);
+ *buflen -= (XDR_QUADLEN(len) << 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(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(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;