Skip to content

Commit

Permalink
nfsd: clean up supported attribute handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
J. Bruce Fields committed Nov 1, 2016
1 parent 851238a commit 916d2d8
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 60 deletions.
43 changes: 11 additions & 32 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,33 +96,12 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{
struct dentry *dentry = cstate->current_fh.fh_dentry;

/*
* 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)))
if (!nfsd_attrs_supported(cstate->minorversion, bmval))
return nfserr_attrnotsupp;

/*
* Check FATTR4_WORD0_ACL can be supported
* in current environment or not.
*/
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;
}

if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
return nfserr_attrnotsupp;
if (writable && !bmval_is_subset(bmval, writable))
return nfserr_inval;
return nfs_ok;
}

Expand Down Expand Up @@ -695,9 +674,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
return nfserr_inval;

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

getattr->ga_fhp = &cstate->current_fh;
return nfs_ok;
Expand Down Expand Up @@ -799,9 +778,9 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
return nfserr_inval;

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

if ((cookie == 1) || (cookie == 2) ||
(cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
Expand Down
38 changes: 24 additions & 14 deletions fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@

#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
* directory in order to indicate to the client that a filesystem boundary is present
Expand Down Expand Up @@ -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);

BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
BUG_ON(!nfsd_attrs_supported(minorversion, bmval));

if (exp->ex_fslocs.migrated) {
status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err);
Expand Down Expand Up @@ -2409,29 +2421,27 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
p++; /* to be backfilled later */

if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
u32 word0 = nfsd_suppattrs0(minorversion);
u32 word1 = nfsd_suppattrs1(minorversion);
u32 word2 = nfsd_suppattrs2(minorversion);
u32 *supp = nfsd_suppattrs[minorversion];

if (!IS_POSIXACL(dentry->d_inode))
word0 &= ~FATTR4_WORD0_ACL;
supp[0] &= ~FATTR4_WORD0_ACL;
if (!contextsupport)
word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
if (!word2) {
supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
if (!supp[2]) {
p = xdr_reserve_space(xdr, 12);
if (!p)
goto out_resource;
*p++ = cpu_to_be32(2);
*p++ = cpu_to_be32(word0);
*p++ = cpu_to_be32(word1);
*p++ = cpu_to_be32(supp[0]);
*p++ = cpu_to_be32(supp[1]);
} else {
p = xdr_reserve_space(xdr, 16);
if (!p)
goto out_resource;
*p++ = cpu_to_be32(3);
*p++ = cpu_to_be32(word0);
*p++ = cpu_to_be32(word1);
*p++ = cpu_to_be32(word2);
*p++ = cpu_to_be32(supp[0]);
*p++ = cpu_to_be32(supp[1]);
*p++ = cpu_to_be32(supp[2]);
}
}
if (bmval0 & FATTR4_WORD0_TYPE) {
Expand Down
21 changes: 7 additions & 14 deletions fs/nfsd/nfsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,25 +361,18 @@ void nfsd_lockd_shutdown(void);
(NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
NFSD4_2_SECURITY_ATTRS)

static inline u32 nfsd_suppattrs0(u32 minorversion)
{
return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
: NFSD4_SUPPORTED_ATTRS_WORD0;
}
extern u32 nfsd_suppattrs[3][3];

static inline u32 nfsd_suppattrs1(u32 minorversion)
static inline bool bmval_is_subset(u32 *bm1, u32 *bm2)
{
return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1
: NFSD4_SUPPORTED_ATTRS_WORD1;
return !((bm1[0] & ~bm2[0]) ||
(bm1[1] & ~bm2[1]) ||
(bm1[2] & ~bm2[2]));
}

static inline u32 nfsd_suppattrs2(u32 minorversion)
static inline bool nfsd_attrs_supported(u32 minorversion, u32 *bmval)
{
switch (minorversion) {
default: return NFSD4_2_SUPPORTED_ATTRS_WORD2;
case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2;
case 0: return NFSD4_SUPPORTED_ATTRS_WORD2;
}
return bmval_is_subset(bmval, nfsd_suppattrs[minorversion]);
}

/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
Expand Down

0 comments on commit 916d2d8

Please sign in to comment.