[pnfs] [PATCH 3/4] nfsd41: SUPPATTR_EXCLCREAT attribute
Benny Halevy
bhalevy at panasas.com
Mon May 12 22:39:05 EDT 2008
Sorry about the noise but please ignore my previous reply since
I've found a few more places that need minorversion attention.
Here's the latest version (might change further while I'm testing it...)
For performance reasons I tried to stick to macros and static inline
functions rather than using global arrays to keep the per-minorversion
word masks. What do you think?
Benny
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index ba1fce7..4661dba 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -533,6 +533,7 @@ static __be32
nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_getattr *getattr)
{
+ u32 minorversion;
__be32 status;
status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
@@ -542,8 +543,10 @@ 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_SUPPORTED_ATTRS_WORD0;
- getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
+ minorversion = nfsd4_compound_minorversion(cstate);
+ getattr->ga_bmval[0] &= nfsd_suppattrs0(minorversion);
+ getattr->ga_bmval[1] &= nfsd_suppattrs1(minorversion);
+ getattr->ga_bmval[2] &= nfsd_suppattrs2(minorversion);
getattr->ga_fhp = &cstate->current_fh;
return nfs_ok;
@@ -631,6 +634,7 @@ static __be32
nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_readdir *readdir)
{
+ u32 minorversion;
u64 cookie = readdir->rd_cookie;
static const nfs4_verifier zeroverf;
@@ -639,8 +643,10 @@ 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_SUPPORTED_ATTRS_WORD0;
- readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
+ minorversion = nfsd4_compound_minorversion(cstate);
+ readdir->rd_bmval[0] &= nfsd_suppattrs0(minorversion);
+ readdir->rd_bmval[1] &= nfsd_suppattrs1(minorversion);
+ readdir->rd_bmval[2] &= nfsd_suppattrs2(minorversion);
if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
(cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
@@ -823,14 +829,17 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{
__be32 *buf, *p;
int count;
+ u32 minorversion;
__be32 status;
status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
return status;
- if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
- || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
+ minorversion = nfsd4_compound_minorversion(cstate);
+ if ((verify->ve_bmval[0] & ~nfsd_suppattrs0(minorversion))
+ || (verify->ve_bmval[1] & ~nfsd_suppattrs1(minorversion))
+ || (verify->ve_bmval[2] & ~nfsd_suppattrs2(minorversion)))
return nfserr_attrnotsupp;
if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
|| (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
@@ -850,7 +859,7 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
cstate->current_fh.fh_export,
cstate->current_fh.fh_dentry, buf,
&count, verify->ve_bmval,
- rqstp, 0);
+ rqstp, 0, verify->ve_minorversion);
/* this means that nfsd4_encode_fattr() ran out of space */
if (status == nfserr_resource && count == 0)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index cf66cc2..c71d517 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -250,8 +250,9 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
if (bmlen > 1)
READ32(bmval[1]);
#if defined(CONFIG_NFSD_V4_1)
- if (bmlen > 2)
+ if (bmlen > 2) {
READ32(bmval[2]);
+ }
#endif /* CONFIG_NFSD_V4_1 */
DECODE_TAIL;
@@ -289,9 +290,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
* According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
* read-only attributes return ERR_INVAL.
*/
- if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) ||
- (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1) ||
- (bmval[2] & ~NFSD_SUPPORTED_ATTRS_WORD2))
+ if ((bmval[0] & ~nfsd_suppattrs0(argp->minorversion)) ||
+ (bmval[1] & ~nfsd_suppattrs1(argp->minorversion)) ||
+ (bmval[2] & ~nfsd_suppattrs2(argp->minorversion)))
return nfserr_attrnotsupp;
if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
(bmval[2] & ~writable[2]))
@@ -824,6 +825,7 @@ nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *read
COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
READ32(readdir->rd_dircount); /* just in case you needed a useless field... */
READ32(readdir->rd_maxcount);
+ readdir->minorversion = argp->minorversion;
if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
goto out;
@@ -1202,6 +1204,7 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
READ32(verify->ve_attrlen);
READ_BUF(verify->ve_attrlen);
SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
+ verify->ve_minorversion = argp->minorversion;
DECODE_TAIL;
}
@@ -1755,7 +1758,7 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
__be32
nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
- struct svc_rqst *rqstp, int ignore_crossmnt)
+ struct svc_rqst *rqstp, int ignore_crossmnt, u32 minorversion)
{
u32 bmval0 = bmval[0];
u32 bmval1 = bmval[1];
@@ -1775,12 +1778,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
struct nfs4_acl *acl = NULL;
BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
- BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
- BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
- if (bmval2 & ~NFSD_SUPPORTED_ATTRS_WORD2) {
- printk(KERN_ERR "%s: bmval2=0x%x\n", __func__, bmval2);
- WARN_ON(1);
- }
+ BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
+ BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
+ BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
if (exp->ex_fslocs.migrated) {
BUG_ON(bmval[2]);
@@ -1845,22 +1845,25 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
attrlenp = p++; /* to be backfilled later */
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)
goto out_resource;
if (!aclsupport)
word0 &= ~FATTR4_WORD0_ACL;
if (!exp->ex_fslocs.locations)
word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
- if (!NFSD_SUPPORTED_ATTRS_WORD2) {
+ if (!word2) {
WRITE32(2);
WRITE32(word0);
- WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
+ WRITE32(word1);
} else {
WRITE32(3);
WRITE32(word0);
- WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
- WRITE32(NFSD_SUPPORTED_ATTRS_WORD2);
+ WRITE32(word1);
+ WRITE32(word2);
}
}
if (bmval0 & FATTR4_WORD0_TYPE) {
@@ -2245,7 +2248,8 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
}
nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
- cd->rd_rqstp, ignore_crossmnt);
+ cd->rd_rqstp, ignore_crossmnt,
+ cd->minorversion);
out_put:
dput(dentry);
exp_put(exp);
@@ -2399,7 +2403,7 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
resp->p, &buflen, getattr->ga_bmval,
- resp->rqstp, 0);
+ resp->rqstp, 0, resp->minorversion);
if (!nfserr)
resp->p += buflen;
return nfserr;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index f9f0467..62a7905 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -313,7 +313,7 @@ extern struct timeval nfssvc_boot;
* TIME_BACKUP (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_CHANGE | FATTR4_WORD0_SIZE | FATTR4_WORD0_LINK_SUPPORT \
| FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR | FATTR4_WORD0_FSID \
@@ -325,7 +325,7 @@ extern struct timeval nfssvc_boot;
| FATTR4_WORD0_MAXFILESIZE | FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME \
| 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_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \
| FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \
@@ -333,11 +333,50 @@ extern struct timeval nfssvc_boot;
| FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \
| FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
+#define NFSD4_SUPPORTED_ATTRS_WORD2 0
+
#if defined(CONFIG_NFSD_V4_1)
-#define NFSD_SUPPORTED_ATTRS_WORD2 \
- FATTR4_WORD2_SUPPATTR_EXCLCREAT
-#else /* CONFIG_NFSD_V4_1) */
-#define NFSD_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 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
+
+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;
+}
+#else /* CONFIG_NFSD_V4_1 */
+static inline u32 nfsd_suppattrs0(u32 minorversion)
+{
+ return NFSD4_SUPPORTED_ATTRS_WORD0;
+}
+
+static inline u32 nfsd_suppattrs1(u32 minorversion)
+{
+ return NFSD4_SUPPORTED_ATTRS_WORD1;
+}
+
+static inline u32 nfsd_suppattrs2(u32 minorversion)
+{
+ return NFSD4_SUPPORTED_ATTRS_WORD2;
+}
#endif /* CONFIG_NFSD_V4_1 */
/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 2988c8c..6715038 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -53,6 +53,15 @@ struct nfsd4_compound_state {
#endif /* CONFIG_NFSD_V4_1 */
};
+static inline u32 nfsd4_compound_minorversion(struct nfsd4_compound_state *cs)
+{
+#if defined(CONFIG_NFSD_V4_1)
+ return cs->current_ses ? 1 : 0;
+#else /* CONFIG_NFSD_V4_1 */
+ return 0;
+#endif /* CONFIG_NFSD_V4_1 */
+}
+
struct nfsd4_change_info {
u32 atomic;
u32 before_ctime_sec;
@@ -271,6 +280,7 @@ struct nfsd4_readdir {
__be32 * buffer;
int buflen;
__be32 * offset;
+ u32 minorversion;
};
struct nfsd4_release_lockowner {
@@ -335,6 +345,7 @@ struct nfsd4_verify {
u32 ve_bmval[3]; /* request */
u32 ve_attrlen; /* request */
char * ve_attrval; /* request */
+ u32 ve_minorversion;
};
struct nfsd4_write {
@@ -477,6 +488,7 @@ struct nfsd4_compoundres {
char * tag;
u32 opcnt;
__be32 * tagp; /* where to encode tag and opcount */
+ u32 minorversion;
};
#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
@@ -500,8 +512,9 @@ int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *,
void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
- struct dentry *dentry, __be32 *buffer, int *countp,
- u32 *bmval, struct svc_rqst *, int ignore_crossmnt);
+ struct dentry *dentry, __be32 *buffer, int *countp,
+ u32 *bmval, struct svc_rqst *, int ignore_crossmnt,
+ u32 minorversion);
extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
struct nfsd4_compound_state *,
struct nfsd4_setclientid *setclid);
On May. 12, 2008, 18:43 -0700, Benny Halevy <bhalevy at panasas.com> wrote:
> How about this?
>
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index ba1fce7..61836c6 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -850,7 +850,7 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> cstate->current_fh.fh_export,
> cstate->current_fh.fh_dentry, buf,
> &count, verify->ve_bmval,
> - rqstp, 0);
> + rqstp, 0, verify->ve_minorversion);
>
> /* this means that nfsd4_encode_fattr() ran out of space */
> if (status == nfserr_resource && count == 0)
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index cf66cc2..7f0e62b 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -250,8 +250,9 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
> if (bmlen > 1)
> READ32(bmval[1]);
> #if defined(CONFIG_NFSD_V4_1)
> - if (bmlen > 2)
> + if (bmlen > 2) {
> READ32(bmval[2]);
> + }
> #endif /* CONFIG_NFSD_V4_1 */
>
> DECODE_TAIL;
> @@ -291,7 +292,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
> */
> if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) ||
> (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1) ||
> - (bmval[2] & ~NFSD_SUPPORTED_ATTRS_WORD2))
> + (bmval[2] & ~(argp->minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2
> + : NFSD_SUPPORTED_ATTRS_WORD2)))
> return nfserr_attrnotsupp;
> if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
> (bmval[2] & ~writable[2]))
> @@ -824,6 +826,7 @@ nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *read
> COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
> READ32(readdir->rd_dircount); /* just in case you needed a useless field... */
> READ32(readdir->rd_maxcount);
> + readdir->minorversion = argp->minorversion;
> if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
> goto out;
>
> @@ -1202,6 +1205,7 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
> READ32(verify->ve_attrlen);
> READ_BUF(verify->ve_attrlen);
> SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
> + verify->ve_minorversion = argp->minorversion;
>
> DECODE_TAIL;
> }
> @@ -1755,7 +1759,7 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
> __be32
> nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
> struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
> - struct svc_rqst *rqstp, int ignore_crossmnt)
> + struct svc_rqst *rqstp, int ignore_crossmnt, u32 minorversion)
> {
> u32 bmval0 = bmval[0];
> u32 bmval1 = bmval[1];
> @@ -1777,10 +1781,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
> BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
> BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
> BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
> - if (bmval2 & ~NFSD_SUPPORTED_ATTRS_WORD2) {
> - printk(KERN_ERR "%s: bmval2=0x%x\n", __func__, bmval2);
> +#if defined(CONFIG_NFSD_V4_1)
> + if (bmval2 & ~NFSD4_1_SUPPORTED_ATTRS_WORD2) {
> + printk(KERN_ERR "%s: bmval2=0x%08x "
> + "supported_attrs_word2=0x%08x\n",
> + __func__, bmval2, (u32)NFSD4_1_SUPPORTED_ATTRS_WORD2);
> + /* FIXME: change to BUG_ON */
> WARN_ON(1);
> }
> +#endif /* CONFIG_NFSD_V4_1 */
>
> if (exp->ex_fslocs.migrated) {
> BUG_ON(bmval[2]);
> @@ -1846,21 +1855,25 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
>
> if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
> u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0;
> + u32 word1 = NFSD_SUPPORTED_ATTRS_WORD1;
> + u32 word2 = minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2
> + : NFSD_SUPPORTED_ATTRS_WORD2;
> +
> if ((buflen -= 12) < 0)
> goto out_resource;
> if (!aclsupport)
> word0 &= ~FATTR4_WORD0_ACL;
> if (!exp->ex_fslocs.locations)
> word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
> - if (!NFSD_SUPPORTED_ATTRS_WORD2) {
> + if (!word2) {
> WRITE32(2);
> WRITE32(word0);
> - WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
> + WRITE32(word1);
> } else {
> WRITE32(3);
> WRITE32(word0);
> - WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
> - WRITE32(NFSD_SUPPORTED_ATTRS_WORD2);
> + WRITE32(word1);
> + WRITE32(word2);
> }
> }
> if (bmval0 & FATTR4_WORD0_TYPE) {
> @@ -2245,7 +2258,8 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
>
> }
> nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
> - cd->rd_rqstp, ignore_crossmnt);
> + cd->rd_rqstp, ignore_crossmnt,
> + cd->minorversion);
> out_put:
> dput(dentry);
> exp_put(exp);
> @@ -2399,7 +2413,7 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
> buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
> nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
> resp->p, &buflen, getattr->ga_bmval,
> - resp->rqstp, 0);
> + resp->rqstp, 0, resp->minorversion);
> if (!nfserr)
> resp->p += buflen;
> return nfserr;
> diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
> index f9f0467..465106b 100644
> --- a/include/linux/nfsd/nfsd.h
> +++ b/include/linux/nfsd/nfsd.h
> @@ -333,11 +333,11 @@ extern struct timeval nfssvc_boot;
> | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \
> | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
>
> -#if defined(CONFIG_NFSD_V4_1)
> -#define NFSD_SUPPORTED_ATTRS_WORD2 \
> - FATTR4_WORD2_SUPPATTR_EXCLCREAT
> -#else /* CONFIG_NFSD_V4_1) */
> #define NFSD_SUPPORTED_ATTRS_WORD2 0
> +
> +#if defined(CONFIG_NFSD_V4_1)
> +#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
> + (NFSD_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
> #endif /* CONFIG_NFSD_V4_1 */
>
> /* These will return ERR_INVAL if specified in GETATTR or READDIR. */
> diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
> index 2988c8c..76f4638 100644
> --- a/include/linux/nfsd/xdr4.h
> +++ b/include/linux/nfsd/xdr4.h
> @@ -271,6 +271,7 @@ struct nfsd4_readdir {
> __be32 * buffer;
> int buflen;
> __be32 * offset;
> + u32 minorversion;
> };
>
> struct nfsd4_release_lockowner {
> @@ -335,6 +336,7 @@ struct nfsd4_verify {
> u32 ve_bmval[3]; /* request */
> u32 ve_attrlen; /* request */
> char * ve_attrval; /* request */
> + u32 ve_minorversion;
> };
>
> struct nfsd4_write {
> @@ -477,6 +479,7 @@ struct nfsd4_compoundres {
> char * tag;
> u32 opcnt;
> __be32 * tagp; /* where to encode tag and opcount */
> + u32 minorversion;
> };
>
> #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
> @@ -500,8 +503,9 @@ int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *,
> void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
> void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
> __be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
> - struct dentry *dentry, __be32 *buffer, int *countp,
> - u32 *bmval, struct svc_rqst *, int ignore_crossmnt);
> + struct dentry *dentry, __be32 *buffer, int *countp,
> + u32 *bmval, struct svc_rqst *, int ignore_crossmnt,
> + u32 minorversion);
> extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
> struct nfsd4_compound_state *,
> struct nfsd4_setclientid *setclid);
>
> On May. 12, 2008, 15:38 -0700, Benny Halevy <bhalevy at panasas.com> wrote:
>> On May. 12, 2008, 15:27 -0700, "J. Bruce Fields" <bfields at fieldses.org> wrote:
>>> On Mon, May 12, 2008 at 11:27:08AM -0700, Benny Halevy wrote:
>>>> Return bitmask for supported EXCLUSIVE4_1 create attributes.
>>>>
>>>> Signed-off-by: Benny Halevy <bhalevy at panasas.com>
>>>> ---
>>>> fs/nfsd/nfs4xdr.c | 9 ++++++++-
>>>> include/linux/nfs4.h | 2 ++
>>>> include/linux/nfsd/nfsd.h | 19 +++++++++++++++++++
>>>> 3 files changed, 29 insertions(+), 1 deletions(-)
>>>>
>>>> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
>>>> index eac9656..8173af8 100644
>>>> --- a/fs/nfsd/nfs4xdr.c
>>>> +++ b/fs/nfsd/nfs4xdr.c
>>>> @@ -2149,7 +2149,14 @@ out_acl:
>>>> }
>>>> WRITE64(stat.ino);
>>>> }
>>>> - BUG_ON(bmval2); /* FIXME: not implemented yet */
>>>> +#if defined(CONFIG_NFSD_V4_1)
>>>> + if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
>>>> + WRITE32(3);
>>>> + WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
>>>> + WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1);
>>>> + WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2);
>>>> + }
>>>> +#endif /* CONFIG_NFSD_V4_1 */
>>>>
>>>> *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
>>>> *countp = p - buffer;
>>>> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
>>>> index f4c8ce2..190f070 100644
>>>> --- a/include/linux/nfs4.h
>>>> +++ b/include/linux/nfs4.h
>>>> @@ -367,6 +367,8 @@ enum lock_type4 {
>>>> #define FATTR4_WORD0_UNIQUE_HANDLES (1UL << 9)
>>>> #define FATTR4_WORD0_LEASE_TIME (1UL << 10)
>>>> #define FATTR4_WORD0_RDATTR_ERROR (1UL << 11)
>>>> +/* Mandatory in NFSv4.1 */
>>>> +#define FATTR4_WORD2_SUPPATTR_EXCLCREAT (1UL << 11)
>>>>
>>>> /* Recommended Attributes */
>>>> #define FATTR4_WORD0_ACL (1UL << 12)
>>>> diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
>>>> index 64b9e45..f9f0467 100644
>>>> --- a/include/linux/nfsd/nfsd.h
>>>> +++ b/include/linux/nfsd/nfsd.h
>>>> @@ -333,7 +333,12 @@ extern struct timeval nfssvc_boot;
>>>> | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \
>>>> | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
>>>>
>>>> +#if defined(CONFIG_NFSD_V4_1)
>>>> +#define NFSD_SUPPORTED_ATTRS_WORD2 \
>>>> + FATTR4_WORD2_SUPPATTR_EXCLCREAT
>>>> +#else /* CONFIG_NFSD_V4_1) */
>>>> #define NFSD_SUPPORTED_ATTRS_WORD2 0
>>>> +#endif /* CONFIG_NFSD_V4_1 */
>>> Won't we eventually need both of those definitions available at runtime,
>>> so that we can answer requests for the supported_attrs attribute from
>>> both 4.0 and 4.1 clients?
>> Yeah, although I'm not sure it actually illegal in NFSv4.0 to return
>> bits for attributes which are not in the spec I agree it's probably safer
>> to mask these out for NFSv4.0 clients like you said.
>>
>> Benny
>>
>>> --b.
>>>
>>>>
>>>> /* These will return ERR_INVAL if specified in GETATTR or READDIR. */
>>>> #define NFSD_WRITEONLY_ATTRS_WORD1 \
>>>> @@ -347,6 +352,20 @@ extern struct timeval nfssvc_boot;
>>>> | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
>>>> #define NFSD_WRITEABLE_ATTRS_WORD2 0
>>>>
>>>> +#if defined(CONFIG_NFSD_V4_1)
>>>> +#define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
>>>> + NFSD_WRITEABLE_ATTRS_WORD0
>>>> +/*
>>>> + * we currently store the exclusive create verifier in the v_{a,m}time
>>>> + * attributes so the client can't set these at create time using EXCLUSIVE4_1
>>>> + */
>>>> +#define NFSD_SUPPATTR_EXCLCREAT_WORD1 \
>>>> + (NFSD_WRITEABLE_ATTRS_WORD1 & \
>>>> + ~(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET))
>>>> +#define NFSD_SUPPATTR_EXCLCREAT_WORD2 \
>>>> + NFSD_WRITEABLE_ATTRS_WORD2
>>>> +#endif /* CONFIG_NFSD_V4_1 */
>>>> +
>>>> #endif /* CONFIG_NFSD_V4 */
>>>>
>>>> #endif /* __KERNEL__ */
>>>> --
>>>> 1.5.3.3
>>>>
>>>> _______________________________________________
>>>> pNFS mailing list
>>>> pNFS at linux-nfs.org
>>>> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
>> _______________________________________________
>> pNFS mailing list
>> pNFS at linux-nfs.org
>> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
>
More information about the pNFS
mailing list