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

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
...@@ -463,8 +463,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -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, ...@@ -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, ...@@ -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))
......
...@@ -236,6 +236,7 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
WRITE32(2); if (unlikely(bmval2)) {
WRITE32(bmval0); WRITE32(3);
WRITE32(bmval1); WRITE32(bmval0);
WRITE32(bmval1);
WRITE32(bmval2);
} else if (likely(bmval1)) {
WRITE32(2);
WRITE32(bmval0);
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;
WRITE32(2); if (!word2) {
WRITE32(word0); WRITE32(2);
WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); WRITE32(word0);
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, ...@@ -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;
......
...@@ -346,7 +346,7 @@ extern struct timeval nfssvc_boot; ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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 */
......
...@@ -102,7 +102,7 @@ struct nfsd4_create { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment