aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c43
-rw-r--r--fs/nfsd/nfs4xdr.c38
-rw-r--r--fs/nfsd/nfsd.h21
3 files changed, 42 insertions, 60 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index abb09b580389..e901cf124e9f 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -96,33 +96,12 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
96{ 96{
97 struct dentry *dentry = cstate->current_fh.fh_dentry; 97 struct dentry *dentry = cstate->current_fh.fh_dentry;
98 98
99 /* 99 if (!nfsd_attrs_supported(cstate->minorversion, bmval))
100 * Check about attributes are supported by the NFSv4 server or not.
101 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
102 */
103 if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
104 (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
105 (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
106 return nfserr_attrnotsupp; 100 return nfserr_attrnotsupp;
107 101 if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
108 /* 102 return nfserr_attrnotsupp;
109 * Check FATTR4_WORD0_ACL can be supported 103 if (writable && !bmval_is_subset(bmval, writable))
110 * in current environment or not. 104 return nfserr_inval;
111 */
112 if (bmval[0] & FATTR4_WORD0_ACL) {
113 if (!IS_POSIXACL(d_inode(dentry)))
114 return nfserr_attrnotsupp;
115 }
116
117 /*
118 * According to spec, read-only attributes return ERR_INVAL.
119 */
120 if (writable) {
121 if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
122 (bmval[2] & ~writable[2]))
123 return nfserr_inval;
124 }
125
126 return nfs_ok; 105 return nfs_ok;
127} 106}
128 107
@@ -695,9 +674,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
695 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 674 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
696 return nfserr_inval; 675 return nfserr_inval;
697 676
698 getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion); 677 getattr->ga_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0];
699 getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); 678 getattr->ga_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1];
700 getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); 679 getattr->ga_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2];
701 680
702 getattr->ga_fhp = &cstate->current_fh; 681 getattr->ga_fhp = &cstate->current_fh;
703 return nfs_ok; 682 return nfs_ok;
@@ -799,9 +778,9 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
799 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 778 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
800 return nfserr_inval; 779 return nfserr_inval;
801 780
802 readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion); 781 readdir->rd_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0];
803 readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); 782 readdir->rd_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1];
804 readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); 783 readdir->rd_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2];
805 784
806 if ((cookie == 1) || (cookie == 2) || 785 if ((cookie == 1) || (cookie == 2) ||
807 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE))) 786 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index c2d2895a1ec1..a99bbb88c6e1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -57,6 +57,20 @@
57 57
58#define NFSDDBG_FACILITY NFSDDBG_XDR 58#define NFSDDBG_FACILITY NFSDDBG_XDR
59 59
60u32 nfsd_suppattrs[3][3] = {
61 {NFSD4_SUPPORTED_ATTRS_WORD0,
62 NFSD4_SUPPORTED_ATTRS_WORD1,
63 NFSD4_SUPPORTED_ATTRS_WORD2},
64
65 {NFSD4_1_SUPPORTED_ATTRS_WORD0,
66 NFSD4_1_SUPPORTED_ATTRS_WORD1,
67 NFSD4_1_SUPPORTED_ATTRS_WORD2},
68
69 {NFSD4_1_SUPPORTED_ATTRS_WORD0,
70 NFSD4_1_SUPPORTED_ATTRS_WORD1,
71 NFSD4_2_SUPPORTED_ATTRS_WORD2},
72};
73
60/* 74/*
61 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing 75 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
62 * directory in order to indicate to the client that a filesystem boundary is present 76 * 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,
2340 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 2354 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2341 2355
2342 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); 2356 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
2343 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion)); 2357 BUG_ON(!nfsd_attrs_supported(minorversion, bmval));
2344 BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
2345 BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
2346 2358
2347 if (exp->ex_fslocs.migrated) { 2359 if (exp->ex_fslocs.migrated) {
2348 status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err); 2360 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,
2409 p++; /* to be backfilled later */ 2421 p++; /* to be backfilled later */
2410 2422
2411 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 2423 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
2412 u32 word0 = nfsd_suppattrs0(minorversion); 2424 u32 *supp = nfsd_suppattrs[minorversion];
2413 u32 word1 = nfsd_suppattrs1(minorversion);
2414 u32 word2 = nfsd_suppattrs2(minorversion);
2415 2425
2416 if (!IS_POSIXACL(dentry->d_inode)) 2426 if (!IS_POSIXACL(dentry->d_inode))
2417 word0 &= ~FATTR4_WORD0_ACL; 2427 supp[0] &= ~FATTR4_WORD0_ACL;
2418 if (!contextsupport) 2428 if (!contextsupport)
2419 word2 &= ~FATTR4_WORD2_SECURITY_LABEL; 2429 supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
2420 if (!word2) { 2430 if (!supp[2]) {
2421 p = xdr_reserve_space(xdr, 12); 2431 p = xdr_reserve_space(xdr, 12);
2422 if (!p) 2432 if (!p)
2423 goto out_resource; 2433 goto out_resource;
2424 *p++ = cpu_to_be32(2); 2434 *p++ = cpu_to_be32(2);
2425 *p++ = cpu_to_be32(word0); 2435 *p++ = cpu_to_be32(supp[0]);
2426 *p++ = cpu_to_be32(word1); 2436 *p++ = cpu_to_be32(supp[1]);
2427 } else { 2437 } else {
2428 p = xdr_reserve_space(xdr, 16); 2438 p = xdr_reserve_space(xdr, 16);
2429 if (!p) 2439 if (!p)
2430 goto out_resource; 2440 goto out_resource;
2431 *p++ = cpu_to_be32(3); 2441 *p++ = cpu_to_be32(3);
2432 *p++ = cpu_to_be32(word0); 2442 *p++ = cpu_to_be32(supp[0]);
2433 *p++ = cpu_to_be32(word1); 2443 *p++ = cpu_to_be32(supp[1]);
2434 *p++ = cpu_to_be32(word2); 2444 *p++ = cpu_to_be32(supp[2]);
2435 } 2445 }
2436 } 2446 }
2437 if (bmval0 & FATTR4_WORD0_TYPE) { 2447 if (bmval0 & FATTR4_WORD0_TYPE) {
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 9446849888d5..a72d4163273a 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -361,25 +361,18 @@ void nfsd_lockd_shutdown(void);
361 (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ 361 (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
362 NFSD4_2_SECURITY_ATTRS) 362 NFSD4_2_SECURITY_ATTRS)
363 363
364static inline u32 nfsd_suppattrs0(u32 minorversion) 364extern u32 nfsd_suppattrs[3][3];
365{
366 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
367 : NFSD4_SUPPORTED_ATTRS_WORD0;
368}
369 365
370static inline u32 nfsd_suppattrs1(u32 minorversion) 366static inline bool bmval_is_subset(u32 *bm1, u32 *bm2)
371{ 367{
372 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1 368 return !((bm1[0] & ~bm2[0]) ||
373 : NFSD4_SUPPORTED_ATTRS_WORD1; 369 (bm1[1] & ~bm2[1]) ||
370 (bm1[2] & ~bm2[2]));
374} 371}
375 372
376static inline u32 nfsd_suppattrs2(u32 minorversion) 373static inline bool nfsd_attrs_supported(u32 minorversion, u32 *bmval)
377{ 374{
378 switch (minorversion) { 375 return bmval_is_subset(bmval, nfsd_suppattrs[minorversion]);
379 default: return NFSD4_2_SUPPORTED_ATTRS_WORD2;
380 case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2;
381 case 0: return NFSD4_SUPPORTED_ATTRS_WORD2;
382 }
383} 376}
384 377
385/* These will return ERR_INVAL if specified in GETATTR or READDIR. */ 378/* These will return ERR_INVAL if specified in GETATTR or READDIR. */