aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-08 18:18:32 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-08 18:18:32 -0500
commitf1517df8701c9f12dae9ce7f43a5d300a6917619 (patch)
treeb7ba72e70fcdf17306d2a488b5b245e578ad52aa /fs/nfsd
parent9d21874da8ec0e0043c85cde8dda173e74ffc24d (diff)
parent175e03101d36c3034f3c80038d4c28838351a7f2 (diff)
Merge tag 'nfsd-4.16' of git://linux-nfs.org/~bfields/linux
Pull nfsd update from Bruce Fields: "A fairly small update this time around. Some cleanup, RDMA fixes, overlayfs fixes, and a fix for an NFSv4 state bug. The bigger deal for nfsd this time around was Jeff Layton's already-merged i_version patches" * tag 'nfsd-4.16' of git://linux-nfs.org/~bfields/linux: svcrdma: Fix Read chunk round-up NFSD: hide unused svcxdr_dupstr() nfsd: store stat times in fill_pre_wcc() instead of inode times nfsd: encode stat->mtime for getattr instead of inode->i_mtime nfsd: return RESOURCE not GARBAGE_ARGS on too many ops nfsd4: don't set lock stateid's sc_type to CLOSED nfsd: Detect unhashed stids in nfsd4_verify_open_stid() sunrpc: remove dead code in svc_sock_setbufsize svcrdma: Post Receives in the Receive completion handler nfsd4: permit layoutget of executable-only files lockd: convert nlm_rqst.a_count from atomic_t to refcount_t lockd: convert nlm_lockowner.count from atomic_t to refcount_t lockd: convert nsm_handle.sm_count from atomic_t to refcount_t
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs3xdr.c31
-rw-r--r--fs/nfsd/nfs4proc.c9
-rw-r--r--fs/nfsd/nfs4state.c6
-rw-r--r--fs/nfsd/nfs4xdr.c16
-rw-r--r--fs/nfsd/nfsfh.h28
-rw-r--r--fs/nfsd/nfsxdr.c1
6 files changed, 55 insertions, 36 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 2758480555fa..1a70581e1cb2 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -251,6 +251,34 @@ encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
251} 251}
252 252
253/* 253/*
254 * Fill in the pre_op attr for the wcc data
255 */
256void fill_pre_wcc(struct svc_fh *fhp)
257{
258 struct inode *inode;
259 struct kstat stat;
260 __be32 err;
261
262 if (fhp->fh_pre_saved)
263 return;
264
265 inode = d_inode(fhp->fh_dentry);
266 err = fh_getattr(fhp, &stat);
267 if (err) {
268 /* Grab the times from inode anyway */
269 stat.mtime = inode->i_mtime;
270 stat.ctime = inode->i_ctime;
271 stat.size = inode->i_size;
272 }
273
274 fhp->fh_pre_mtime = stat.mtime;
275 fhp->fh_pre_ctime = stat.ctime;
276 fhp->fh_pre_size = stat.size;
277 fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
278 fhp->fh_pre_saved = true;
279}
280
281/*
254 * Fill in the post_op attr for the wcc data 282 * Fill in the post_op attr for the wcc data
255 */ 283 */
256void fill_post_wcc(struct svc_fh *fhp) 284void fill_post_wcc(struct svc_fh *fhp)
@@ -261,7 +289,8 @@ void fill_post_wcc(struct svc_fh *fhp)
261 printk("nfsd: inode locked twice during operation.\n"); 289 printk("nfsd: inode locked twice during operation.\n");
262 290
263 err = fh_getattr(fhp, &fhp->fh_post_attr); 291 err = fh_getattr(fhp, &fhp->fh_post_attr);
264 fhp->fh_post_change = nfsd4_change_attribute(d_inode(fhp->fh_dentry)); 292 fhp->fh_post_change = nfsd4_change_attribute(&fhp->fh_post_attr,
293 d_inode(fhp->fh_dentry));
265 if (err) { 294 if (err) {
266 fhp->fh_post_saved = false; 295 fhp->fh_post_saved = false;
267 /* Grab the ctime anyway - set_change_info might use it */ 296 /* Grab the ctime anyway - set_change_info might use it */
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 008ea0b627d0..a0bed2b2004d 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1363,14 +1363,14 @@ nfsd4_layoutget(struct svc_rqst *rqstp,
1363 const struct nfsd4_layout_ops *ops; 1363 const struct nfsd4_layout_ops *ops;
1364 struct nfs4_layout_stateid *ls; 1364 struct nfs4_layout_stateid *ls;
1365 __be32 nfserr; 1365 __be32 nfserr;
1366 int accmode; 1366 int accmode = NFSD_MAY_READ_IF_EXEC;
1367 1367
1368 switch (lgp->lg_seg.iomode) { 1368 switch (lgp->lg_seg.iomode) {
1369 case IOMODE_READ: 1369 case IOMODE_READ:
1370 accmode = NFSD_MAY_READ; 1370 accmode |= NFSD_MAY_READ;
1371 break; 1371 break;
1372 case IOMODE_RW: 1372 case IOMODE_RW:
1373 accmode = NFSD_MAY_READ | NFSD_MAY_WRITE; 1373 accmode |= NFSD_MAY_READ | NFSD_MAY_WRITE;
1374 break; 1374 break;
1375 default: 1375 default:
1376 dprintk("%s: invalid iomode %d\n", 1376 dprintk("%s: invalid iomode %d\n",
@@ -1703,6 +1703,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
1703 status = nfserr_minor_vers_mismatch; 1703 status = nfserr_minor_vers_mismatch;
1704 if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) 1704 if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
1705 goto out; 1705 goto out;
1706 status = nfserr_resource;
1707 if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
1708 goto out;
1706 1709
1707 status = nfs41_check_op_ordering(args); 1710 status = nfs41_check_op_ordering(args);
1708 if (status) { 1711 if (status) {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b29b5a185a2c..150521c9671b 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3590,6 +3590,7 @@ nfsd4_verify_open_stid(struct nfs4_stid *s)
3590 switch (s->sc_type) { 3590 switch (s->sc_type) {
3591 default: 3591 default:
3592 break; 3592 break;
3593 case 0:
3593 case NFS4_CLOSED_STID: 3594 case NFS4_CLOSED_STID:
3594 case NFS4_CLOSED_DELEG_STID: 3595 case NFS4_CLOSED_DELEG_STID:
3595 ret = nfserr_bad_stateid; 3596 ret = nfserr_bad_stateid;
@@ -5182,7 +5183,6 @@ nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)
5182 lockowner(stp->st_stateowner))) 5183 lockowner(stp->st_stateowner)))
5183 goto out; 5184 goto out;
5184 5185
5185 stp->st_stid.sc_type = NFS4_CLOSED_STID;
5186 release_lock_stateid(stp); 5186 release_lock_stateid(stp);
5187 ret = nfs_ok; 5187 ret = nfs_ok;
5188 5188
@@ -6078,10 +6078,8 @@ out:
6078 * If this is a new, never-before-used stateid, and we are 6078 * If this is a new, never-before-used stateid, and we are
6079 * returning an error, then just go ahead and release it. 6079 * returning an error, then just go ahead and release it.
6080 */ 6080 */
6081 if (status && new) { 6081 if (status && new)
6082 lock_stp->st_stid.sc_type = NFS4_CLOSED_STID;
6083 release_lock_stateid(lock_stp); 6082 release_lock_stateid(lock_stp);
6084 }
6085 6083
6086 mutex_unlock(&lock_stp->st_mutex); 6084 mutex_unlock(&lock_stp->st_mutex);
6087 6085
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2c61c6b8ae09..e502fd16246b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -455,8 +455,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
455 } 455 }
456 456
457 label->len = 0; 457 label->len = 0;
458#ifdef CONFIG_NFSD_V4_SECURITY_LABEL 458 if (IS_ENABLED(CONFIG_NFSD_V4_SECURITY_LABEL) &&
459 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) { 459 bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
460 READ_BUF(4); 460 READ_BUF(4);
461 len += 4; 461 len += 4;
462 dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */ 462 dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */
@@ -476,7 +476,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
476 if (!label->data) 476 if (!label->data)
477 return nfserr_jukebox; 477 return nfserr_jukebox;
478 } 478 }
479#endif
480 if (bmval[2] & FATTR4_WORD2_MODE_UMASK) { 479 if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
481 if (!umask) 480 if (!umask)
482 goto xdr_error; 481 goto xdr_error;
@@ -1918,8 +1917,13 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1918 1917
1919 if (argp->taglen > NFSD4_MAX_TAGLEN) 1918 if (argp->taglen > NFSD4_MAX_TAGLEN)
1920 goto xdr_error; 1919 goto xdr_error;
1921 if (argp->opcnt > 100) 1920 /*
1922 goto xdr_error; 1921 * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
1922 * here, so we return success at the xdr level so that
1923 * nfsd4_proc can handle this is an NFS-level error.
1924 */
1925 if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
1926 return 0;
1923 1927
1924 if (argp->opcnt > ARRAY_SIZE(argp->iops)) { 1928 if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
1925 argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); 1929 argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
@@ -1991,7 +1995,7 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
1991 *p++ = cpu_to_be32(convert_to_wallclock(exp->cd->flush_time)); 1995 *p++ = cpu_to_be32(convert_to_wallclock(exp->cd->flush_time));
1992 *p++ = 0; 1996 *p++ = 0;
1993 } else if (IS_I_VERSION(inode)) { 1997 } else if (IS_I_VERSION(inode)) {
1994 p = xdr_encode_hyper(p, nfsd4_change_attribute(inode)); 1998 p = xdr_encode_hyper(p, nfsd4_change_attribute(stat, inode));
1995 } else { 1999 } else {
1996 *p++ = cpu_to_be32(stat->ctime.tv_sec); 2000 *p++ = cpu_to_be32(stat->ctime.tv_sec);
1997 *p++ = cpu_to_be32(stat->ctime.tv_nsec); 2001 *p++ = cpu_to_be32(stat->ctime.tv_nsec);
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
index b8444189223b..755e256a9103 100644
--- a/fs/nfsd/nfsfh.h
+++ b/fs/nfsd/nfsfh.h
@@ -253,36 +253,20 @@ fh_clear_wcc(struct svc_fh *fhp)
253 * By using both ctime and the i_version counter we guarantee that as 253 * By using both ctime and the i_version counter we guarantee that as
254 * long as time doesn't go backwards we never reuse an old value. 254 * long as time doesn't go backwards we never reuse an old value.
255 */ 255 */
256static inline u64 nfsd4_change_attribute(struct inode *inode) 256static inline u64 nfsd4_change_attribute(struct kstat *stat,
257 struct inode *inode)
257{ 258{
258 u64 chattr; 259 u64 chattr;
259 260
260 chattr = inode->i_ctime.tv_sec; 261 chattr = stat->ctime.tv_sec;
261 chattr <<= 30; 262 chattr <<= 30;
262 chattr += inode->i_ctime.tv_nsec; 263 chattr += stat->ctime.tv_nsec;
263 chattr += inode_query_iversion(inode); 264 chattr += inode_query_iversion(inode);
264 return chattr; 265 return chattr;
265} 266}
266 267
267/* 268extern void fill_pre_wcc(struct svc_fh *fhp);
268 * Fill in the pre_op attr for the wcc data 269extern void fill_post_wcc(struct svc_fh *fhp);
269 */
270static inline void
271fill_pre_wcc(struct svc_fh *fhp)
272{
273 struct inode *inode;
274
275 inode = d_inode(fhp->fh_dentry);
276 if (!fhp->fh_pre_saved) {
277 fhp->fh_pre_mtime = inode->i_mtime;
278 fhp->fh_pre_ctime = inode->i_ctime;
279 fhp->fh_pre_size = inode->i_size;
280 fhp->fh_pre_change = nfsd4_change_attribute(inode);
281 fhp->fh_pre_saved = true;
282 }
283}
284
285extern void fill_post_wcc(struct svc_fh *);
286#else 270#else
287#define fh_clear_wcc(ignored) 271#define fh_clear_wcc(ignored)
288#define fill_pre_wcc(ignored) 272#define fill_pre_wcc(ignored)
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 644a0342f0e0..79b6064f8977 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -188,6 +188,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
188 *p++ = htonl((u32) stat->ino); 188 *p++ = htonl((u32) stat->ino);
189 *p++ = htonl((u32) stat->atime.tv_sec); 189 *p++ = htonl((u32) stat->atime.tv_sec);
190 *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0); 190 *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
191 time = stat->mtime;
191 lease_get_mtime(d_inode(dentry), &time); 192 lease_get_mtime(d_inode(dentry), &time);
192 *p++ = htonl((u32) time.tv_sec); 193 *p++ = htonl((u32) time.tv_sec);
193 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); 194 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0);