diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-08 18:18:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-08 18:18:32 -0500 |
commit | f1517df8701c9f12dae9ce7f43a5d300a6917619 (patch) | |
tree | b7ba72e70fcdf17306d2a488b5b245e578ad52aa /fs/nfsd | |
parent | 9d21874da8ec0e0043c85cde8dda173e74ffc24d (diff) | |
parent | 175e03101d36c3034f3c80038d4c28838351a7f2 (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.c | 31 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 9 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 16 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.h | 28 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 1 |
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 | */ | ||
256 | void 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 | */ |
256 | void fill_post_wcc(struct svc_fh *fhp) | 284 | void 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 | */ |
256 | static inline u64 nfsd4_change_attribute(struct inode *inode) | 256 | static 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 | /* | 268 | extern void fill_pre_wcc(struct svc_fh *fhp); |
268 | * Fill in the pre_op attr for the wcc data | 269 | extern void fill_post_wcc(struct svc_fh *fhp); |
269 | */ | ||
270 | static inline void | ||
271 | fill_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 | |||
285 | extern 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); |