nfsd: clean up supported attribute handling

Minor cleanup, no change in behavior.

Provide helpers for some common attribute bitmap operations.  Drop some
comments that just echo the code.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
J. Bruce Fields 2016-10-18 14:18:40 -04:00
parent 851238a22f
commit 916d2d844a
3 changed files with 43 additions and 61 deletions

View file

@ -96,33 +96,12 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{ {
struct dentry *dentry = cstate->current_fh.fh_dentry; struct dentry *dentry = cstate->current_fh.fh_dentry;
/* if (!nfsd_attrs_supported(cstate->minorversion, bmval))
* Check about attributes are supported by the NFSv4 server or not.
* According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
*/
if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
(bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
(bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
return nfserr_attrnotsupp; return nfserr_attrnotsupp;
if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
/* return nfserr_attrnotsupp;
* Check FATTR4_WORD0_ACL can be supported if (writable && !bmval_is_subset(bmval, writable))
* in current environment or not. return nfserr_inval;
*/
if (bmval[0] & FATTR4_WORD0_ACL) {
if (!IS_POSIXACL(d_inode(dentry)))
return nfserr_attrnotsupp;
}
/*
* According to spec, read-only attributes return ERR_INVAL.
*/
if (writable) {
if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
(bmval[2] & ~writable[2]))
return nfserr_inval;
}
return nfs_ok; return nfs_ok;
} }
@ -695,9 +674,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_suppattrs0(cstate->minorversion); getattr->ga_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0];
getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); getattr->ga_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1];
getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); getattr->ga_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2];
getattr->ga_fhp = &cstate->current_fh; getattr->ga_fhp = &cstate->current_fh;
return nfs_ok; return nfs_ok;
@ -799,9 +778,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_suppattrs0(cstate->minorversion); readdir->rd_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0];
readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); readdir->rd_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1];
readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); readdir->rd_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2];
if ((cookie == 1) || (cookie == 2) || if ((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)))

View file

@ -57,6 +57,20 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR #define NFSDDBG_FACILITY NFSDDBG_XDR
u32 nfsd_suppattrs[3][3] = {
{NFSD4_SUPPORTED_ATTRS_WORD0,
NFSD4_SUPPORTED_ATTRS_WORD1,
NFSD4_SUPPORTED_ATTRS_WORD2},
{NFSD4_1_SUPPORTED_ATTRS_WORD0,
NFSD4_1_SUPPORTED_ATTRS_WORD1,
NFSD4_1_SUPPORTED_ATTRS_WORD2},
{NFSD4_1_SUPPORTED_ATTRS_WORD0,
NFSD4_1_SUPPORTED_ATTRS_WORD1,
NFSD4_2_SUPPORTED_ATTRS_WORD2},
};
/* /*
* As per referral draft, the fsid for a referral MUST be different from the fsid of the containing * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
* directory in order to indicate to the client that a filesystem boundary is present * directory in order to indicate to the client that a filesystem boundary is present
@ -2340,9 +2354,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion)); BUG_ON(!nfsd_attrs_supported(minorversion, bmval));
BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
if (exp->ex_fslocs.migrated) { if (exp->ex_fslocs.migrated) {
status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err); status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err);
@ -2409,29 +2421,27 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
p++; /* to be backfilled later */ p++; /* to be backfilled later */
if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
u32 word0 = nfsd_suppattrs0(minorversion); u32 *supp = nfsd_suppattrs[minorversion];
u32 word1 = nfsd_suppattrs1(minorversion);
u32 word2 = nfsd_suppattrs2(minorversion);
if (!IS_POSIXACL(dentry->d_inode)) if (!IS_POSIXACL(dentry->d_inode))
word0 &= ~FATTR4_WORD0_ACL; supp[0] &= ~FATTR4_WORD0_ACL;
if (!contextsupport) if (!contextsupport)
word2 &= ~FATTR4_WORD2_SECURITY_LABEL; supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
if (!word2) { if (!supp[2]) {
p = xdr_reserve_space(xdr, 12); p = xdr_reserve_space(xdr, 12);
if (!p) if (!p)
goto out_resource; goto out_resource;
*p++ = cpu_to_be32(2); *p++ = cpu_to_be32(2);
*p++ = cpu_to_be32(word0); *p++ = cpu_to_be32(supp[0]);
*p++ = cpu_to_be32(word1); *p++ = cpu_to_be32(supp[1]);
} else { } else {
p = xdr_reserve_space(xdr, 16); p = xdr_reserve_space(xdr, 16);
if (!p) if (!p)
goto out_resource; goto out_resource;
*p++ = cpu_to_be32(3); *p++ = cpu_to_be32(3);
*p++ = cpu_to_be32(word0); *p++ = cpu_to_be32(supp[0]);
*p++ = cpu_to_be32(word1); *p++ = cpu_to_be32(supp[1]);
*p++ = cpu_to_be32(word2); *p++ = cpu_to_be32(supp[2]);
} }
} }
if (bmval0 & FATTR4_WORD0_TYPE) { if (bmval0 & FATTR4_WORD0_TYPE) {

View file

@ -361,25 +361,18 @@ void nfsd_lockd_shutdown(void);
(NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
NFSD4_2_SECURITY_ATTRS) NFSD4_2_SECURITY_ATTRS)
static inline u32 nfsd_suppattrs0(u32 minorversion) extern u32 nfsd_suppattrs[3][3];
static inline bool bmval_is_subset(u32 *bm1, u32 *bm2)
{ {
return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 return !((bm1[0] & ~bm2[0]) ||
: NFSD4_SUPPORTED_ATTRS_WORD0; (bm1[1] & ~bm2[1]) ||
(bm1[2] & ~bm2[2]));
} }
static inline u32 nfsd_suppattrs1(u32 minorversion) static inline bool nfsd_attrs_supported(u32 minorversion, u32 *bmval)
{ {
return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1 return bmval_is_subset(bmval, nfsd_suppattrs[minorversion]);
: NFSD4_SUPPORTED_ATTRS_WORD1;
}
static inline u32 nfsd_suppattrs2(u32 minorversion)
{
switch (minorversion) {
default: return NFSD4_2_SUPPORTED_ATTRS_WORD2;
case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2;
case 0: return 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. */