aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c15
-rw-r--r--fs/nfsd/nfs4xdr.c59
-rw-r--r--include/linux/nfsd/nfsd.h34
-rw-r--r--include/linux/nfsd/xdr4.h12
4 files changed, 94 insertions, 26 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 937853f62834..e206053433e3 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -463,8 +463,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
463 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 463 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
464 return nfserr_inval; 464 return nfserr_inval;
465 465
466 getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; 466 getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
467 getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; 467 getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
468 getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
468 469
469 getattr->ga_fhp = &cstate->current_fh; 470 getattr->ga_fhp = &cstate->current_fh;
470 return nfs_ok; 471 return nfs_ok;
@@ -555,8 +556,9 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
555 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 556 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
556 return nfserr_inval; 557 return nfserr_inval;
557 558
558 readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; 559 readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
559 readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; 560 readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
561 readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
560 562
561 if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) || 563 if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
562 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE))) 564 (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 if (status) 748 if (status)
747 return status; 749 return status;
748 750
749 if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) 751 if ((verify->ve_bmval[0] & ~nfsd_suppattrs0(cstate->minorversion))
750 || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) 752 || (verify->ve_bmval[1] & ~nfsd_suppattrs1(cstate->minorversion))
753 || (verify->ve_bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
751 return nfserr_attrnotsupp; 754 return nfserr_attrnotsupp;
752 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR) 755 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
753 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)) 756 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 42f9fb661006..70296fedee41 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -236,6 +236,7 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
236 236
237 bmval[0] = 0; 237 bmval[0] = 0;
238 bmval[1] = 0; 238 bmval[1] = 0;
239 bmval[2] = 0;
239 240
240 READ_BUF(4); 241 READ_BUF(4);
241 READ32(bmlen); 242 READ32(bmlen);
@@ -247,13 +248,16 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
247 READ32(bmval[0]); 248 READ32(bmval[0]);
248 if (bmlen > 1) 249 if (bmlen > 1)
249 READ32(bmval[1]); 250 READ32(bmval[1]);
251 if (bmlen > 2)
252 READ32(bmval[2]);
250 253
251 DECODE_TAIL; 254 DECODE_TAIL;
252} 255}
253 256
254static u32 nfsd_attrmask[] = { 257static u32 nfsd_attrmask[] = {
255 NFSD_WRITEABLE_ATTRS_WORD0, 258 NFSD_WRITEABLE_ATTRS_WORD0,
256 NFSD_WRITEABLE_ATTRS_WORD1 259 NFSD_WRITEABLE_ATTRS_WORD1,
260 NFSD_WRITEABLE_ATTRS_WORD2
257}; 261};
258 262
259static __be32 263static __be32
@@ -274,9 +278,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
274 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP; 278 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
275 * read-only attributes return ERR_INVAL. 279 * read-only attributes return ERR_INVAL.
276 */ 280 */
277 if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) 281 if ((bmval[0] & ~nfsd_suppattrs0(argp->minorversion)) ||
282 (bmval[1] & ~nfsd_suppattrs1(argp->minorversion)) ||
283 (bmval[2] & ~nfsd_suppattrs2(argp->minorversion)))
278 return nfserr_attrnotsupp; 284 return nfserr_attrnotsupp;
279 if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1])) 285 if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
286 (bmval[2] & ~writable[2]))
280 return nfserr_inval; 287 return nfserr_inval;
281 288
282 READ_BUF(4); 289 READ_BUF(4);
@@ -411,6 +418,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
411 goto xdr_error; 418 goto xdr_error;
412 } 419 }
413 } 420 }
421 BUG_ON(bmval[2]); /* no such writeable attr supported yet */
414 if (len != expected_len) 422 if (len != expected_len)
415 goto xdr_error; 423 goto xdr_error;
416 424
@@ -1726,6 +1734,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1726{ 1734{
1727 u32 bmval0 = bmval[0]; 1735 u32 bmval0 = bmval[0];
1728 u32 bmval1 = bmval[1]; 1736 u32 bmval1 = bmval[1];
1737 u32 bmval2 = bmval[2];
1729 struct kstat stat; 1738 struct kstat stat;
1730 struct svc_fh tempfh; 1739 struct svc_fh tempfh;
1731 struct kstatfs statfs; 1740 struct kstatfs statfs;
@@ -1739,12 +1748,16 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1739 int err; 1748 int err;
1740 int aclsupport = 0; 1749 int aclsupport = 0;
1741 struct nfs4_acl *acl = NULL; 1750 struct nfs4_acl *acl = NULL;
1751 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1752 u32 minorversion = resp->cstate.minorversion;
1742 1753
1743 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); 1754 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1744 BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); 1755 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
1745 BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); 1756 BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
1757 BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
1746 1758
1747 if (exp->ex_fslocs.migrated) { 1759 if (exp->ex_fslocs.migrated) {
1760 BUG_ON(bmval[2]);
1748 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err); 1761 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
1749 if (status) 1762 if (status)
1750 goto out; 1763 goto out;
@@ -1790,22 +1803,42 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1790 if ((buflen -= 16) < 0) 1803 if ((buflen -= 16) < 0)
1791 goto out_resource; 1804 goto out_resource;
1792 1805
1793 WRITE32(2); 1806 if (unlikely(bmval2)) {
1794 WRITE32(bmval0); 1807 WRITE32(3);
1795 WRITE32(bmval1); 1808 WRITE32(bmval0);
1809 WRITE32(bmval1);
1810 WRITE32(bmval2);
1811 } else if (likely(bmval1)) {
1812 WRITE32(2);
1813 WRITE32(bmval0);
1814 WRITE32(bmval1);
1815 } else {
1816 WRITE32(1);
1817 WRITE32(bmval0);
1818 }
1796 attrlenp = p++; /* to be backfilled later */ 1819 attrlenp = p++; /* to be backfilled later */
1797 1820
1798 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 1821 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1799 u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0; 1822 u32 word0 = nfsd_suppattrs0(minorversion);
1823 u32 word1 = nfsd_suppattrs1(minorversion);
1824 u32 word2 = nfsd_suppattrs2(minorversion);
1825
1800 if ((buflen -= 12) < 0) 1826 if ((buflen -= 12) < 0)
1801 goto out_resource; 1827 goto out_resource;
1802 if (!aclsupport) 1828 if (!aclsupport)
1803 word0 &= ~FATTR4_WORD0_ACL; 1829 word0 &= ~FATTR4_WORD0_ACL;
1804 if (!exp->ex_fslocs.locations) 1830 if (!exp->ex_fslocs.locations)
1805 word0 &= ~FATTR4_WORD0_FS_LOCATIONS; 1831 word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
1806 WRITE32(2); 1832 if (!word2) {
1807 WRITE32(word0); 1833 WRITE32(2);
1808 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); 1834 WRITE32(word0);
1835 WRITE32(word1);
1836 } else {
1837 WRITE32(3);
1838 WRITE32(word0);
1839 WRITE32(word1);
1840 WRITE32(word2);
1841 }
1809 } 1842 }
1810 if (bmval0 & FATTR4_WORD0_TYPE) { 1843 if (bmval0 & FATTR4_WORD0_TYPE) {
1811 if ((buflen -= 4) < 0) 1844 if ((buflen -= 4) < 0)
@@ -2115,6 +2148,8 @@ out_acl:
2115 } 2148 }
2116 WRITE64(stat.ino); 2149 WRITE64(stat.ino);
2117 } 2150 }
2151 BUG_ON(bmval2); /* FIXME: not implemented yet */
2152
2118 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 2153 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2119 *countp = p - buffer; 2154 *countp = p - buffer;
2120 status = nfs_ok; 2155 status = nfs_ok;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 5bed5096874d..69ca788f8fc5 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -346,7 +346,7 @@ extern struct timeval nfssvc_boot;
346 * TIME_BACKUP (unlikely to be supported any time soon) 346 * TIME_BACKUP (unlikely to be supported any time soon)
347 * TIME_CREATE (unlikely to be supported any time soon) 347 * TIME_CREATE (unlikely to be supported any time soon)
348 */ 348 */
349#define NFSD_SUPPORTED_ATTRS_WORD0 \ 349#define NFSD4_SUPPORTED_ATTRS_WORD0 \
350(FATTR4_WORD0_SUPPORTED_ATTRS | FATTR4_WORD0_TYPE | FATTR4_WORD0_FH_EXPIRE_TYPE \ 350(FATTR4_WORD0_SUPPORTED_ATTRS | FATTR4_WORD0_TYPE | FATTR4_WORD0_FH_EXPIRE_TYPE \
351 | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE | FATTR4_WORD0_LINK_SUPPORT \ 351 | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE | FATTR4_WORD0_LINK_SUPPORT \
352 | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR | FATTR4_WORD0_FSID \ 352 | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR | FATTR4_WORD0_FSID \
@@ -358,7 +358,7 @@ extern struct timeval nfssvc_boot;
358 | FATTR4_WORD0_MAXFILESIZE | FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME \ 358 | FATTR4_WORD0_MAXFILESIZE | FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME \
359 | FATTR4_WORD0_MAXREAD | FATTR4_WORD0_MAXWRITE | FATTR4_WORD0_ACL) 359 | FATTR4_WORD0_MAXREAD | FATTR4_WORD0_MAXWRITE | FATTR4_WORD0_ACL)
360 360
361#define NFSD_SUPPORTED_ATTRS_WORD1 \ 361#define NFSD4_SUPPORTED_ATTRS_WORD1 \
362(FATTR4_WORD1_MODE | FATTR4_WORD1_NO_TRUNC | FATTR4_WORD1_NUMLINKS \ 362(FATTR4_WORD1_MODE | FATTR4_WORD1_NO_TRUNC | FATTR4_WORD1_NUMLINKS \
363 | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \ 363 | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \
364 | FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \ 364 | FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \
@@ -366,6 +366,35 @@ extern struct timeval nfssvc_boot;
366 | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \ 366 | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \
367 | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID) 367 | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
368 368
369#define NFSD4_SUPPORTED_ATTRS_WORD2 0
370
371#define NFSD4_1_SUPPORTED_ATTRS_WORD0 \
372 NFSD4_SUPPORTED_ATTRS_WORD0
373
374#define NFSD4_1_SUPPORTED_ATTRS_WORD1 \
375 NFSD4_SUPPORTED_ATTRS_WORD1
376
377#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
378 NFSD4_SUPPORTED_ATTRS_WORD2
379
380static inline u32 nfsd_suppattrs0(u32 minorversion)
381{
382 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
383 : NFSD4_SUPPORTED_ATTRS_WORD0;
384}
385
386static inline u32 nfsd_suppattrs1(u32 minorversion)
387{
388 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1
389 : NFSD4_SUPPORTED_ATTRS_WORD1;
390}
391
392static inline u32 nfsd_suppattrs2(u32 minorversion)
393{
394 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2
395 : NFSD4_SUPPORTED_ATTRS_WORD2;
396}
397
369/* These will return ERR_INVAL if specified in GETATTR or READDIR. */ 398/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
370#define NFSD_WRITEONLY_ATTRS_WORD1 \ 399#define NFSD_WRITEONLY_ATTRS_WORD1 \
371(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 400(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
@@ -376,6 +405,7 @@ extern struct timeval nfssvc_boot;
376#define NFSD_WRITEABLE_ATTRS_WORD1 \ 405#define NFSD_WRITEABLE_ATTRS_WORD1 \
377(FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ 406(FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
378 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 407 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
408#define NFSD_WRITEABLE_ATTRS_WORD2 0
379 409
380#endif /* CONFIG_NFSD_V4 */ 410#endif /* CONFIG_NFSD_V4 */
381 411
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 5e16935a1eaf..c07d8fe7bb07 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -102,7 +102,7 @@ struct nfsd4_create {
102 u32 specdata2; 102 u32 specdata2;
103 } dev; /* NF4BLK, NF4CHR */ 103 } dev; /* NF4BLK, NF4CHR */
104 } u; 104 } u;
105 u32 cr_bmval[2]; /* request */ 105 u32 cr_bmval[3]; /* request */
106 struct iattr cr_iattr; /* request */ 106 struct iattr cr_iattr; /* request */
107 struct nfsd4_change_info cr_cinfo; /* response */ 107 struct nfsd4_change_info cr_cinfo; /* response */
108 struct nfs4_acl *cr_acl; 108 struct nfs4_acl *cr_acl;
@@ -117,7 +117,7 @@ struct nfsd4_delegreturn {
117}; 117};
118 118
119struct nfsd4_getattr { 119struct nfsd4_getattr {
120 u32 ga_bmval[2]; /* request */ 120 u32 ga_bmval[3]; /* request */
121 struct svc_fh *ga_fhp; /* response */ 121 struct svc_fh *ga_fhp; /* response */
122}; 122};
123 123
@@ -218,7 +218,7 @@ struct nfsd4_open {
218 stateid_t op_delegate_stateid; /* request - response */ 218 stateid_t op_delegate_stateid; /* request - response */
219 u32 op_create; /* request */ 219 u32 op_create; /* request */
220 u32 op_createmode; /* request */ 220 u32 op_createmode; /* request */
221 u32 op_bmval[2]; /* request */ 221 u32 op_bmval[3]; /* request */
222 union { /* request */ 222 union { /* request */
223 struct iattr iattr; /* UNCHECKED4,GUARDED4 */ 223 struct iattr iattr; /* UNCHECKED4,GUARDED4 */
224 nfs4_verifier verf; /* EXCLUSIVE4 */ 224 nfs4_verifier verf; /* EXCLUSIVE4 */
@@ -271,7 +271,7 @@ struct nfsd4_readdir {
271 nfs4_verifier rd_verf; /* request */ 271 nfs4_verifier rd_verf; /* request */
272 u32 rd_dircount; /* request */ 272 u32 rd_dircount; /* request */
273 u32 rd_maxcount; /* request */ 273 u32 rd_maxcount; /* request */
274 u32 rd_bmval[2]; /* request */ 274 u32 rd_bmval[3]; /* request */
275 struct svc_rqst *rd_rqstp; /* response */ 275 struct svc_rqst *rd_rqstp; /* response */
276 struct svc_fh * rd_fhp; /* response */ 276 struct svc_fh * rd_fhp; /* response */
277 277
@@ -313,7 +313,7 @@ struct nfsd4_secinfo {
313 313
314struct nfsd4_setattr { 314struct nfsd4_setattr {
315 stateid_t sa_stateid; /* request */ 315 stateid_t sa_stateid; /* request */
316 u32 sa_bmval[2]; /* request */ 316 u32 sa_bmval[3]; /* request */
317 struct iattr sa_iattr; /* request */ 317 struct iattr sa_iattr; /* request */
318 struct nfs4_acl *sa_acl; 318 struct nfs4_acl *sa_acl;
319}; 319};
@@ -339,7 +339,7 @@ struct nfsd4_setclientid_confirm {
339 339
340/* also used for NVERIFY */ 340/* also used for NVERIFY */
341struct nfsd4_verify { 341struct nfsd4_verify {
342 u32 ve_bmval[2]; /* request */ 342 u32 ve_bmval[3]; /* request */
343 u32 ve_attrlen; /* request */ 343 u32 ve_attrlen; /* request */
344 char * ve_attrval; /* request */ 344 char * ve_attrval; /* request */
345}; 345};