Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e705706 authored by Andy Adamson's avatar Andy Adamson Committed by J. Bruce Fields
Browse files

nfsd41: support for 3-word long attribute bitmask



Also, use client minorversion to generate supported attrs

Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 95ec28cd
Loading
Loading
Loading
Loading
+9 −6
Original line number Original line Diff line number Diff line
@@ -463,8 +463,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
	if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
		return nfserr_inval;
		return nfserr_inval;


	getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
	getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
	getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
	getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
	getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);


	getattr->ga_fhp = &cstate->current_fh;
	getattr->ga_fhp = &cstate->current_fh;
	return nfs_ok;
	return nfs_ok;
@@ -555,8 +556,9 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
	if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
		return nfserr_inval;
		return nfserr_inval;


	readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
	readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
	readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
	readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
	readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);


	if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
	if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
	    (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
	    (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
@@ -746,8 +748,9 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	if (status)
	if (status)
		return status;
		return status;


	if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
	if ((verify->ve_bmval[0] & ~nfsd_suppattrs0(cstate->minorversion))
	    || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
	    || (verify->ve_bmval[1] & ~nfsd_suppattrs1(cstate->minorversion))
	    || (verify->ve_bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
		return nfserr_attrnotsupp;
		return nfserr_attrnotsupp;
	if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
	if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
	    || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
	    || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
+47 −12
Original line number Original line Diff line number Diff line
@@ -236,6 +236,7 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)


	bmval[0] = 0;
	bmval[0] = 0;
	bmval[1] = 0;
	bmval[1] = 0;
	bmval[2] = 0;


	READ_BUF(4);
	READ_BUF(4);
	READ32(bmlen);
	READ32(bmlen);
@@ -247,13 +248,16 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
		READ32(bmval[0]);
		READ32(bmval[0]);
	if (bmlen > 1)
	if (bmlen > 1)
		READ32(bmval[1]);
		READ32(bmval[1]);
	if (bmlen > 2)
		READ32(bmval[2]);


	DECODE_TAIL;
	DECODE_TAIL;
}
}


static u32 nfsd_attrmask[] = {
static u32 nfsd_attrmask[] = {
	NFSD_WRITEABLE_ATTRS_WORD0,
	NFSD_WRITEABLE_ATTRS_WORD0,
	NFSD_WRITEABLE_ATTRS_WORD1
	NFSD_WRITEABLE_ATTRS_WORD1,
	NFSD_WRITEABLE_ATTRS_WORD2
};
};


static __be32
static __be32
@@ -274,9 +278,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
	 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
	 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
	 * read-only attributes return ERR_INVAL.
	 * read-only attributes return ERR_INVAL.
	 */
	 */
	if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
	if ((bmval[0] & ~nfsd_suppattrs0(argp->minorversion)) ||
	    (bmval[1] & ~nfsd_suppattrs1(argp->minorversion)) ||
	    (bmval[2] & ~nfsd_suppattrs2(argp->minorversion)))
		return nfserr_attrnotsupp;
		return nfserr_attrnotsupp;
	if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]))
	if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
	    (bmval[2] & ~writable[2]))
		return nfserr_inval;
		return nfserr_inval;


	READ_BUF(4);
	READ_BUF(4);
@@ -411,6 +418,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
			goto xdr_error;
			goto xdr_error;
		}
		}
	}
	}
	BUG_ON(bmval[2]);	/* no such writeable attr supported yet */
	if (len != expected_len)
	if (len != expected_len)
		goto xdr_error;
		goto xdr_error;


@@ -1726,6 +1734,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
{
{
	u32 bmval0 = bmval[0];
	u32 bmval0 = bmval[0];
	u32 bmval1 = bmval[1];
	u32 bmval1 = bmval[1];
	u32 bmval2 = bmval[2];
	struct kstat stat;
	struct kstat stat;
	struct svc_fh tempfh;
	struct svc_fh tempfh;
	struct kstatfs statfs;
	struct kstatfs statfs;
@@ -1739,12 +1748,16 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
	int err;
	int err;
	int aclsupport = 0;
	int aclsupport = 0;
	struct nfs4_acl *acl = NULL;
	struct nfs4_acl *acl = NULL;
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
	u32 minorversion = resp->cstate.minorversion;


	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
	BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
	BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
	BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
	BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
	BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));


	if (exp->ex_fslocs.migrated) {
	if (exp->ex_fslocs.migrated) {
		BUG_ON(bmval[2]);
		status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
		status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
		if (status)
		if (status)
			goto out;
			goto out;
@@ -1790,22 +1803,42 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
	if ((buflen -= 16) < 0)
	if ((buflen -= 16) < 0)
		goto out_resource;
		goto out_resource;


	if (unlikely(bmval2)) {
		WRITE32(3);
		WRITE32(bmval0);
		WRITE32(bmval1);
		WRITE32(bmval2);
	} else if (likely(bmval1)) {
		WRITE32(2);
		WRITE32(2);
		WRITE32(bmval0);
		WRITE32(bmval0);
		WRITE32(bmval1);
		WRITE32(bmval1);
	} else {
		WRITE32(1);
		WRITE32(bmval0);
	}
	attrlenp = p++;                /* to be backfilled later */
	attrlenp = p++;                /* to be backfilled later */


	if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
	if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
		u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0;
		u32 word0 = nfsd_suppattrs0(minorversion);
		u32 word1 = nfsd_suppattrs1(minorversion);
		u32 word2 = nfsd_suppattrs2(minorversion);

		if ((buflen -= 12) < 0)
		if ((buflen -= 12) < 0)
			goto out_resource;
			goto out_resource;
		if (!aclsupport)
		if (!aclsupport)
			word0 &= ~FATTR4_WORD0_ACL;
			word0 &= ~FATTR4_WORD0_ACL;
		if (!exp->ex_fslocs.locations)
		if (!exp->ex_fslocs.locations)
			word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
			word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
		if (!word2) {
			WRITE32(2);
			WRITE32(2);
			WRITE32(word0);
			WRITE32(word0);
		WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
			WRITE32(word1);
		} else {
			WRITE32(3);
			WRITE32(word0);
			WRITE32(word1);
			WRITE32(word2);
		}
	}
	}
	if (bmval0 & FATTR4_WORD0_TYPE) {
	if (bmval0 & FATTR4_WORD0_TYPE) {
		if ((buflen -= 4) < 0)
		if ((buflen -= 4) < 0)
@@ -2115,6 +2148,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
		}
		}
		WRITE64(stat.ino);
		WRITE64(stat.ino);
	}
	}
	BUG_ON(bmval2);	/* FIXME: not implemented yet */

	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
	*countp = p - buffer;
	*countp = p - buffer;
	status = nfs_ok;
	status = nfs_ok;
+32 −2
Original line number Original line Diff line number Diff line
@@ -346,7 +346,7 @@ extern struct timeval nfssvc_boot;
 *    TIME_BACKUP   (unlikely to be supported any time soon)
 *    TIME_BACKUP   (unlikely to be supported any time soon)
 *    TIME_CREATE   (unlikely to be supported any time soon)
 *    TIME_CREATE   (unlikely to be supported any time soon)
 */
 */
#define NFSD_SUPPORTED_ATTRS_WORD0                                                          \
#define NFSD4_SUPPORTED_ATTRS_WORD0                                                         \
(FATTR4_WORD0_SUPPORTED_ATTRS   | FATTR4_WORD0_TYPE         | FATTR4_WORD0_FH_EXPIRE_TYPE   \
(FATTR4_WORD0_SUPPORTED_ATTRS   | FATTR4_WORD0_TYPE         | FATTR4_WORD0_FH_EXPIRE_TYPE   \
 | FATTR4_WORD0_CHANGE          | FATTR4_WORD0_SIZE         | FATTR4_WORD0_LINK_SUPPORT     \
 | FATTR4_WORD0_CHANGE          | FATTR4_WORD0_SIZE         | FATTR4_WORD0_LINK_SUPPORT     \
 | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR   | FATTR4_WORD0_FSID             \
 | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR   | FATTR4_WORD0_FSID             \
@@ -358,7 +358,7 @@ extern struct timeval nfssvc_boot;
 | FATTR4_WORD0_MAXFILESIZE     | FATTR4_WORD0_MAXLINK      | FATTR4_WORD0_MAXNAME          \
 | FATTR4_WORD0_MAXFILESIZE     | FATTR4_WORD0_MAXLINK      | FATTR4_WORD0_MAXNAME          \
 | FATTR4_WORD0_MAXREAD         | FATTR4_WORD0_MAXWRITE     | FATTR4_WORD0_ACL)
 | FATTR4_WORD0_MAXREAD         | FATTR4_WORD0_MAXWRITE     | FATTR4_WORD0_ACL)


#define NFSD_SUPPORTED_ATTRS_WORD1                                                          \
#define NFSD4_SUPPORTED_ATTRS_WORD1                                                         \
(FATTR4_WORD1_MODE              | FATTR4_WORD1_NO_TRUNC     | FATTR4_WORD1_NUMLINKS         \
(FATTR4_WORD1_MODE              | FATTR4_WORD1_NO_TRUNC     | FATTR4_WORD1_NUMLINKS         \
 | FATTR4_WORD1_OWNER	        | FATTR4_WORD1_OWNER_GROUP  | FATTR4_WORD1_RAWDEV           \
 | FATTR4_WORD1_OWNER	        | FATTR4_WORD1_OWNER_GROUP  | FATTR4_WORD1_RAWDEV           \
 | FATTR4_WORD1_SPACE_AVAIL     | FATTR4_WORD1_SPACE_FREE   | FATTR4_WORD1_SPACE_TOTAL      \
 | FATTR4_WORD1_SPACE_AVAIL     | FATTR4_WORD1_SPACE_FREE   | FATTR4_WORD1_SPACE_TOTAL      \
@@ -366,6 +366,35 @@ extern struct timeval nfssvc_boot;
 | FATTR4_WORD1_TIME_DELTA   | FATTR4_WORD1_TIME_METADATA    \
 | FATTR4_WORD1_TIME_DELTA   | FATTR4_WORD1_TIME_METADATA    \
 | FATTR4_WORD1_TIME_MODIFY     | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
 | FATTR4_WORD1_TIME_MODIFY     | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)


#define NFSD4_SUPPORTED_ATTRS_WORD2 0

#define NFSD4_1_SUPPORTED_ATTRS_WORD0 \
	NFSD4_SUPPORTED_ATTRS_WORD0

#define NFSD4_1_SUPPORTED_ATTRS_WORD1 \
	NFSD4_SUPPORTED_ATTRS_WORD1

#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
	NFSD4_SUPPORTED_ATTRS_WORD2

static inline u32 nfsd_suppattrs0(u32 minorversion)
{
	return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
			    : NFSD4_SUPPORTED_ATTRS_WORD0;
}

static inline u32 nfsd_suppattrs1(u32 minorversion)
{
	return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1
			    : NFSD4_SUPPORTED_ATTRS_WORD1;
}

static inline u32 nfsd_suppattrs2(u32 minorversion)
{
	return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2
			    : NFSD4_SUPPORTED_ATTRS_WORD2;
}

/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
#define NFSD_WRITEONLY_ATTRS_WORD1							    \
#define NFSD_WRITEONLY_ATTRS_WORD1							    \
(FATTR4_WORD1_TIME_ACCESS_SET   | FATTR4_WORD1_TIME_MODIFY_SET)
(FATTR4_WORD1_TIME_ACCESS_SET   | FATTR4_WORD1_TIME_MODIFY_SET)
@@ -376,6 +405,7 @@ extern struct timeval nfssvc_boot;
#define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
#define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
(FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
(FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
#define NFSD_WRITEABLE_ATTRS_WORD2 0


#endif /* CONFIG_NFSD_V4 */
#endif /* CONFIG_NFSD_V4 */


+6 −6
Original line number Original line Diff line number Diff line
@@ -102,7 +102,7 @@ struct nfsd4_create {
			u32 specdata2;
			u32 specdata2;
		} dev;    /* NF4BLK, NF4CHR */
		} dev;    /* NF4BLK, NF4CHR */
	} u;
	} u;
	u32		cr_bmval[2];        /* request */
	u32		cr_bmval[3];        /* request */
	struct iattr	cr_iattr;           /* request */
	struct iattr	cr_iattr;           /* request */
	struct nfsd4_change_info  cr_cinfo; /* response */
	struct nfsd4_change_info  cr_cinfo; /* response */
	struct nfs4_acl *cr_acl;
	struct nfs4_acl *cr_acl;
@@ -117,7 +117,7 @@ struct nfsd4_delegreturn {
};
};


struct nfsd4_getattr {
struct nfsd4_getattr {
	u32		ga_bmval[2];        /* request */
	u32		ga_bmval[3];        /* request */
	struct svc_fh	*ga_fhp;            /* response */
	struct svc_fh	*ga_fhp;            /* response */
};
};


@@ -218,7 +218,7 @@ struct nfsd4_open {
	stateid_t       op_delegate_stateid; /* request - response */
	stateid_t       op_delegate_stateid; /* request - response */
	u32		op_create;     	    /* request */
	u32		op_create;     	    /* request */
	u32		op_createmode;      /* request */
	u32		op_createmode;      /* request */
	u32		op_bmval[2];        /* request */
	u32		op_bmval[3];        /* request */
	union {                             /* request */
	union {                             /* request */
		struct iattr	iattr;                      /* UNCHECKED4,GUARDED4 */
		struct iattr	iattr;                      /* UNCHECKED4,GUARDED4 */
		nfs4_verifier	verf;                                /* EXCLUSIVE4 */
		nfs4_verifier	verf;                                /* EXCLUSIVE4 */
@@ -271,7 +271,7 @@ struct nfsd4_readdir {
	nfs4_verifier	rd_verf;            /* request */
	nfs4_verifier	rd_verf;            /* request */
	u32		rd_dircount;        /* request */
	u32		rd_dircount;        /* request */
	u32		rd_maxcount;        /* request */
	u32		rd_maxcount;        /* request */
	u32		rd_bmval[2];        /* request */
	u32		rd_bmval[3];        /* request */
	struct svc_rqst *rd_rqstp;          /* response */
	struct svc_rqst *rd_rqstp;          /* response */
	struct svc_fh * rd_fhp;             /* response */
	struct svc_fh * rd_fhp;             /* response */


@@ -313,7 +313,7 @@ struct nfsd4_secinfo {


struct nfsd4_setattr {
struct nfsd4_setattr {
	stateid_t	sa_stateid;         /* request */
	stateid_t	sa_stateid;         /* request */
	u32		sa_bmval[2];        /* request */
	u32		sa_bmval[3];        /* request */
	struct iattr	sa_iattr;           /* request */
	struct iattr	sa_iattr;           /* request */
	struct nfs4_acl *sa_acl;
	struct nfs4_acl *sa_acl;
};
};
@@ -339,7 +339,7 @@ struct nfsd4_setclientid_confirm {


/* also used for NVERIFY */
/* also used for NVERIFY */
struct nfsd4_verify {
struct nfsd4_verify {
	u32		ve_bmval[2];        /* request */
	u32		ve_bmval[3];        /* request */
	u32		ve_attrlen;         /* request */
	u32		ve_attrlen;         /* request */
	char *		ve_attrval;         /* request */
	char *		ve_attrval;         /* request */
};
};