Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd updates from Chuck Lever:
"Mike Snitzer has prototyped a mechanism for disabling I/O caching in
NFSD. This is introduced in v6.18 as an experimental feature. This
enables scaling NFSD in /both/ directions:

- NFS service can be supported on systems with small memory
footprints, such as low-cost cloud instances

- Large NFS workloads will be less likely to force the eviction of
server-local activity, helping it avoid thrashing

Jeff Layton contributed a number of fixes to the new attribute
delegation implementation (based on a pending Internet RFC) that we
hope will make attribute delegation reliable enough to enable by
default, as it is on the Linux NFS client.

The remaining patches in this pull request are clean-ups and minor
optimizations. Many thanks to the contributors, reviewers, testers,
and bug reporters who participated during the v6.18 NFSD development
cycle"

* tag 'nfsd-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (42 commits)
nfsd: discard nfserr_dropit
SUNRPC: Make RPCSEC_GSS_KRB5 select CRYPTO instead of depending on it
NFSD: Add io_cache_{read,write} controls to debugfs
NFSD: Do the grace period check in ->proc_layoutget
nfsd: delete unnecessary NULL check in __fh_verify()
NFSD: Allow layoutcommit during grace period
NFSD: Disallow layoutget during grace period
sunrpc: fix "occurence"->"occurrence"
nfsd: Don't force CRYPTO_LIB_SHA256 to be built-in
nfsd: nfserr_jukebox in nlm_fopen should lead to a retry
NFSD: Reduce DRC bucket size
NFSD: Delay adding new entries to LRU
SUNRPC: Move the svc_rpcb_cleanup() call sites
NFS: Remove rpcbind cleanup for NFSv4.0 callback
nfsd: unregister with rpcbind when deleting a transport
NFSD: Drop redundant conversion to bool
sunrpc: eliminate return pointer in svc_tcp_sendmsg()
sunrpc: fix pr_notice in svc_tcp_sendto() to show correct length
nfsd: decouple the xprtsec policy check from check_nfsd_access()
NFSD: Fix destination buffer size in nfsd4_ssc_setup_dul()
...

+665 -325
+19 -25
fs/attr.c
··· 286 286 unsigned int ia_valid = attr->ia_valid; 287 287 struct timespec64 now; 288 288 289 - if (ia_valid & ATTR_CTIME) { 290 - /* 291 - * In the case of an update for a write delegation, we must respect 292 - * the value in ia_ctime and not use the current time. 293 - */ 294 - if (ia_valid & ATTR_DELEG) 295 - now = inode_set_ctime_deleg(inode, attr->ia_ctime); 296 - else 297 - now = inode_set_ctime_current(inode); 298 - } else { 299 - /* If ATTR_CTIME isn't set, then ATTR_MTIME shouldn't be either. */ 300 - WARN_ON_ONCE(ia_valid & ATTR_MTIME); 289 + if (ia_valid & ATTR_CTIME_SET) 290 + now = inode_set_ctime_deleg(inode, attr->ia_ctime); 291 + else if (ia_valid & ATTR_CTIME) 292 + now = inode_set_ctime_current(inode); 293 + else 301 294 now = current_time(inode); 302 - } 303 295 304 296 if (ia_valid & ATTR_ATIME_SET) 305 297 inode_set_atime_to_ts(inode, attr->ia_atime); ··· 351 359 inode_set_atime_to_ts(inode, attr->ia_atime); 352 360 if (ia_valid & ATTR_MTIME) 353 361 inode_set_mtime_to_ts(inode, attr->ia_mtime); 354 - if (ia_valid & ATTR_CTIME) { 355 - if (ia_valid & ATTR_DELEG) 356 - inode_set_ctime_deleg(inode, attr->ia_ctime); 357 - else 358 - inode_set_ctime_to_ts(inode, attr->ia_ctime); 359 - } 362 + 363 + if (ia_valid & ATTR_CTIME_SET) 364 + inode_set_ctime_deleg(inode, attr->ia_ctime); 365 + else if (ia_valid & ATTR_CTIME) 366 + inode_set_ctime_to_ts(inode, attr->ia_ctime); 360 367 } 361 368 EXPORT_SYMBOL(setattr_copy); 362 369 ··· 454 463 455 464 now = current_time(inode); 456 465 457 - attr->ia_ctime = now; 458 - if (!(ia_valid & ATTR_ATIME_SET)) 459 - attr->ia_atime = now; 460 - else 466 + if (ia_valid & ATTR_ATIME_SET) 461 467 attr->ia_atime = timestamp_truncate(attr->ia_atime, inode); 462 - if (!(ia_valid & ATTR_MTIME_SET)) 463 - attr->ia_mtime = now; 464 468 else 469 + attr->ia_atime = now; 470 + if (ia_valid & ATTR_CTIME_SET) 471 + attr->ia_ctime = timestamp_truncate(attr->ia_ctime, inode); 472 + else 473 + attr->ia_ctime = now; 474 + if (ia_valid & ATTR_MTIME_SET) 465 475 attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode); 476 + else 477 + attr->ia_mtime = now; 466 478 467 479 if (ia_valid & ATTR_KILL_PRIV) { 468 480 error = security_inode_need_killpriv(dentry);
+1 -1
fs/lockd/svclock.c
··· 980 980 struct file_lock *fl; 981 981 int error; 982 982 983 - dprintk("grant_reply: looking for cookie %x, s=%d \n", 983 + dprintk("grant_reply: looking for cookie %x, s=%d\n", 984 984 *(unsigned int *)(cookie->data), status); 985 985 if (!(block = nlmsvc_find_block(cookie))) 986 986 return;
+1 -1
fs/nfsd/Kconfig
··· 5 5 depends on FILE_LOCKING 6 6 depends on FSNOTIFY 7 7 select CRC32 8 + select CRYPTO_LIB_SHA256 if NFSD_V4 8 9 select LOCKD 9 10 select SUNRPC 10 11 select EXPORTFS ··· 78 77 select FS_POSIX_ACL 79 78 select RPCSEC_GSS_KRB5 80 79 select CRYPTO 81 - select CRYPTO_LIB_SHA256 82 80 select CRYPTO_MD5 83 81 select GRACE_PERIOD 84 82 select NFS_V4_2_SSC_HELPER if NFS_V4_2
+19 -13
fs/nfsd/blocklayout.c
··· 18 18 19 19 20 20 static __be32 21 - nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, 22 - struct nfsd4_layoutget *args) 21 + nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode, 22 + const struct svc_fh *fhp, struct nfsd4_layoutget *args) 23 23 { 24 24 struct nfsd4_layout_seg *seg = &args->lg_seg; 25 25 struct super_block *sb = inode->i_sb; ··· 28 28 struct iomap iomap; 29 29 u32 device_generation = 0; 30 30 int error; 31 + 32 + if (locks_in_grace(SVC_NET(rqstp))) 33 + return nfserr_grace; 31 34 32 35 if (seg->offset & (block_size - 1)) { 33 36 dprintk("pnfsd: I/O misaligned\n"); ··· 121 118 struct iomap *iomaps, int nr_iomaps) 122 119 { 123 120 struct timespec64 mtime = inode_get_mtime(inode); 124 - loff_t new_size = lcp->lc_last_wr + 1; 125 121 struct iattr iattr = { .ia_valid = 0 }; 126 122 int error; 127 123 ··· 130 128 iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME; 131 129 iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; 132 130 133 - if (new_size > i_size_read(inode)) { 131 + if (lcp->lc_size_chg) { 134 132 iattr.ia_valid |= ATTR_SIZE; 135 - iattr.ia_size = new_size; 133 + iattr.ia_size = lcp->lc_newsize; 136 134 } 137 135 138 136 error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps, ··· 175 173 } 176 174 177 175 static __be32 178 - nfsd4_block_proc_layoutcommit(struct inode *inode, 176 + nfsd4_block_proc_layoutcommit(struct inode *inode, struct svc_rqst *rqstp, 179 177 struct nfsd4_layoutcommit *lcp) 180 178 { 181 179 struct iomap *iomaps; 182 180 int nr_iomaps; 183 181 __be32 nfserr; 184 182 185 - nfserr = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, 186 - lcp->lc_up_len, &iomaps, &nr_iomaps, 187 - i_blocksize(inode)); 183 + rqstp->rq_arg = lcp->lc_up_layout; 184 + svcxdr_init_decode(rqstp); 185 + 186 + nfserr = nfsd4_block_decode_layoutupdate(&rqstp->rq_arg_stream, 187 + &iomaps, &nr_iomaps, i_blocksize(inode)); 188 188 if (nfserr != nfs_ok) 189 189 return nfserr; 190 190 ··· 317 313 return nfserrno(nfsd4_block_get_device_info_scsi(sb, clp, gdp)); 318 314 } 319 315 static __be32 320 - nfsd4_scsi_proc_layoutcommit(struct inode *inode, 316 + nfsd4_scsi_proc_layoutcommit(struct inode *inode, struct svc_rqst *rqstp, 321 317 struct nfsd4_layoutcommit *lcp) 322 318 { 323 319 struct iomap *iomaps; 324 320 int nr_iomaps; 325 321 __be32 nfserr; 326 322 327 - nfserr = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout, 328 - lcp->lc_up_len, &iomaps, &nr_iomaps, 329 - i_blocksize(inode)); 323 + rqstp->rq_arg = lcp->lc_up_layout; 324 + svcxdr_init_decode(rqstp); 325 + 326 + nfserr = nfsd4_scsi_decode_layoutupdate(&rqstp->rq_arg_stream, 327 + &iomaps, &nr_iomaps, i_blocksize(inode)); 330 328 if (nfserr != nfs_ok) 331 329 return nfserr; 332 330
+56 -30
fs/nfsd/blocklayoutxdr.c
··· 29 29 *p++ = cpu_to_be32(len); 30 30 *p++ = cpu_to_be32(1); /* we always return a single extent */ 31 31 32 - p = xdr_encode_opaque_fixed(p, &b->vol_id, 33 - sizeof(struct nfsd4_deviceid)); 32 + p = svcxdr_encode_deviceid4(p, &b->vol_id); 34 33 p = xdr_encode_hyper(p, b->foff); 35 34 p = xdr_encode_hyper(p, b->len); 36 35 p = xdr_encode_hyper(p, b->soff); ··· 113 114 114 115 /** 115 116 * nfsd4_block_decode_layoutupdate - decode the block layout extent array 116 - * @p: pointer to the xdr data 117 - * @len: number of bytes to decode 117 + * @xdr: subbuf set to the encoded array 118 118 * @iomapp: pointer to store the decoded extent array 119 119 * @nr_iomapsp: pointer to store the number of extents 120 120 * @block_size: alignment of extent offset and length ··· 126 128 * 127 129 * Return values: 128 130 * %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid 129 - * %nfserr_bad_xdr: The encoded array in @p is invalid 131 + * %nfserr_bad_xdr: The encoded array in @xdr is invalid 130 132 * %nfserr_inval: An unaligned extent found 131 133 * %nfserr_delay: Failed to allocate memory for @iomapp 132 134 */ 133 135 __be32 134 - nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, 136 + nfsd4_block_decode_layoutupdate(struct xdr_stream *xdr, struct iomap **iomapp, 135 137 int *nr_iomapsp, u32 block_size) 136 138 { 137 139 struct iomap *iomaps; 138 - u32 nr_iomaps, i; 140 + u32 nr_iomaps, expected, len, i; 141 + __be32 nfserr; 139 142 140 - if (len < sizeof(u32)) 141 - return nfserr_bad_xdr; 142 - len -= sizeof(u32); 143 - if (len % PNFS_BLOCK_EXTENT_SIZE) 143 + if (xdr_stream_decode_u32(xdr, &nr_iomaps)) 144 144 return nfserr_bad_xdr; 145 145 146 - nr_iomaps = be32_to_cpup(p++); 147 - if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) 146 + len = sizeof(__be32) + xdr_stream_remaining(xdr); 147 + expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE; 148 + if (len != expected) 148 149 return nfserr_bad_xdr; 149 150 150 151 iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL); ··· 153 156 for (i = 0; i < nr_iomaps; i++) { 154 157 struct pnfs_block_extent bex; 155 158 156 - memcpy(&bex.vol_id, p, sizeof(struct nfsd4_deviceid)); 157 - p += XDR_QUADLEN(sizeof(struct nfsd4_deviceid)); 159 + if (nfsd4_decode_deviceid4(xdr, &bex.vol_id)) { 160 + nfserr = nfserr_bad_xdr; 161 + goto fail; 162 + } 158 163 159 - p = xdr_decode_hyper(p, &bex.foff); 164 + if (xdr_stream_decode_u64(xdr, &bex.foff)) { 165 + nfserr = nfserr_bad_xdr; 166 + goto fail; 167 + } 160 168 if (bex.foff & (block_size - 1)) { 169 + nfserr = nfserr_inval; 161 170 goto fail; 162 171 } 163 - p = xdr_decode_hyper(p, &bex.len); 172 + 173 + if (xdr_stream_decode_u64(xdr, &bex.len)) { 174 + nfserr = nfserr_bad_xdr; 175 + goto fail; 176 + } 164 177 if (bex.len & (block_size - 1)) { 178 + nfserr = nfserr_inval; 165 179 goto fail; 166 180 } 167 - p = xdr_decode_hyper(p, &bex.soff); 181 + 182 + if (xdr_stream_decode_u64(xdr, &bex.soff)) { 183 + nfserr = nfserr_bad_xdr; 184 + goto fail; 185 + } 168 186 if (bex.soff & (block_size - 1)) { 187 + nfserr = nfserr_inval; 169 188 goto fail; 170 189 } 171 - bex.es = be32_to_cpup(p++); 190 + 191 + if (xdr_stream_decode_u32(xdr, &bex.es)) { 192 + nfserr = nfserr_bad_xdr; 193 + goto fail; 194 + } 172 195 if (bex.es != PNFS_BLOCK_READWRITE_DATA) { 196 + nfserr = nfserr_inval; 173 197 goto fail; 174 198 } 175 199 ··· 203 185 return nfs_ok; 204 186 fail: 205 187 kfree(iomaps); 206 - return nfserr_inval; 188 + return nfserr; 207 189 } 208 190 209 191 /** 210 192 * nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array 211 - * @p: pointer to the xdr data 212 - * @len: number of bytes to decode 193 + * @xdr: subbuf set to the encoded array 213 194 * @iomapp: pointer to store the decoded extent array 214 195 * @nr_iomapsp: pointer to store the number of extents 215 196 * @block_size: alignment of extent offset and length ··· 220 203 * 221 204 * Return values: 222 205 * %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid 223 - * %nfserr_bad_xdr: The encoded array in @p is invalid 206 + * %nfserr_bad_xdr: The encoded array in @xdr is invalid 224 207 * %nfserr_inval: An unaligned extent found 225 208 * %nfserr_delay: Failed to allocate memory for @iomapp 226 209 */ 227 210 __be32 228 - nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, 211 + nfsd4_scsi_decode_layoutupdate(struct xdr_stream *xdr, struct iomap **iomapp, 229 212 int *nr_iomapsp, u32 block_size) 230 213 { 231 214 struct iomap *iomaps; 232 - u32 nr_iomaps, expected, i; 215 + u32 nr_iomaps, expected, len, i; 216 + __be32 nfserr; 233 217 234 - if (len < sizeof(u32)) 218 + if (xdr_stream_decode_u32(xdr, &nr_iomaps)) 235 219 return nfserr_bad_xdr; 236 220 237 - nr_iomaps = be32_to_cpup(p++); 221 + len = sizeof(__be32) + xdr_stream_remaining(xdr); 238 222 expected = sizeof(__be32) + nr_iomaps * PNFS_SCSI_RANGE_SIZE; 239 223 if (len != expected) 240 224 return nfserr_bad_xdr; ··· 247 229 for (i = 0; i < nr_iomaps; i++) { 248 230 u64 val; 249 231 250 - p = xdr_decode_hyper(p, &val); 232 + if (xdr_stream_decode_u64(xdr, &val)) { 233 + nfserr = nfserr_bad_xdr; 234 + goto fail; 235 + } 251 236 if (val & (block_size - 1)) { 237 + nfserr = nfserr_inval; 252 238 goto fail; 253 239 } 254 240 iomaps[i].offset = val; 255 241 256 - p = xdr_decode_hyper(p, &val); 242 + if (xdr_stream_decode_u64(xdr, &val)) { 243 + nfserr = nfserr_bad_xdr; 244 + goto fail; 245 + } 257 246 if (val & (block_size - 1)) { 247 + nfserr = nfserr_inval; 258 248 goto fail; 259 249 } 260 250 iomaps[i].length = val; ··· 273 247 return nfs_ok; 274 248 fail: 275 249 kfree(iomaps); 276 - return nfserr_inval; 250 + return nfserr; 277 251 }
+2 -2
fs/nfsd/blocklayoutxdr.h
··· 54 54 const struct nfsd4_getdeviceinfo *gdp); 55 55 __be32 nfsd4_block_encode_layoutget(struct xdr_stream *xdr, 56 56 const struct nfsd4_layoutget *lgp); 57 - __be32 nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, 57 + __be32 nfsd4_block_decode_layoutupdate(struct xdr_stream *xdr, 58 58 struct iomap **iomapp, int *nr_iomapsp, u32 block_size); 59 - __be32 nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, 59 + __be32 nfsd4_scsi_decode_layoutupdate(struct xdr_stream *xdr, 60 60 struct iomap **iomapp, int *nr_iomapsp, u32 block_size); 61 61 62 62 #endif /* _NFSD_BLOCKLAYOUTXDR_H */
+94 -1
fs/nfsd/debugfs.c
··· 26 26 27 27 static int nfsd_dsr_set(void *data, u64 val) 28 28 { 29 - nfsd_disable_splice_read = (val > 0) ? true : false; 29 + nfsd_disable_splice_read = (val > 0); 30 + if (!nfsd_disable_splice_read) { 31 + /* 32 + * Must use buffered I/O if splice_read is enabled. 33 + */ 34 + nfsd_io_cache_read = NFSD_IO_BUFFERED; 35 + } 30 36 return 0; 31 37 } 32 38 33 39 DEFINE_DEBUGFS_ATTRIBUTE(nfsd_dsr_fops, nfsd_dsr_get, nfsd_dsr_set, "%llu\n"); 40 + 41 + /* 42 + * /sys/kernel/debug/nfsd/io_cache_read 43 + * 44 + * Contents: 45 + * %0: NFS READ will use buffered IO 46 + * %1: NFS READ will use dontcache (buffered IO w/ dropbehind) 47 + * 48 + * This setting takes immediate effect for all NFS versions, 49 + * all exports, and in all NFSD net namespaces. 50 + */ 51 + 52 + static int nfsd_io_cache_read_get(void *data, u64 *val) 53 + { 54 + *val = nfsd_io_cache_read; 55 + return 0; 56 + } 57 + 58 + static int nfsd_io_cache_read_set(void *data, u64 val) 59 + { 60 + int ret = 0; 61 + 62 + switch (val) { 63 + case NFSD_IO_BUFFERED: 64 + nfsd_io_cache_read = NFSD_IO_BUFFERED; 65 + break; 66 + case NFSD_IO_DONTCACHE: 67 + /* 68 + * Must disable splice_read when enabling 69 + * NFSD_IO_DONTCACHE. 70 + */ 71 + nfsd_disable_splice_read = true; 72 + nfsd_io_cache_read = val; 73 + break; 74 + default: 75 + ret = -EINVAL; 76 + break; 77 + } 78 + 79 + return ret; 80 + } 81 + 82 + DEFINE_DEBUGFS_ATTRIBUTE(nfsd_io_cache_read_fops, nfsd_io_cache_read_get, 83 + nfsd_io_cache_read_set, "%llu\n"); 84 + 85 + /* 86 + * /sys/kernel/debug/nfsd/io_cache_write 87 + * 88 + * Contents: 89 + * %0: NFS WRITE will use buffered IO 90 + * %1: NFS WRITE will use dontcache (buffered IO w/ dropbehind) 91 + * 92 + * This setting takes immediate effect for all NFS versions, 93 + * all exports, and in all NFSD net namespaces. 94 + */ 95 + 96 + static int nfsd_io_cache_write_get(void *data, u64 *val) 97 + { 98 + *val = nfsd_io_cache_write; 99 + return 0; 100 + } 101 + 102 + static int nfsd_io_cache_write_set(void *data, u64 val) 103 + { 104 + int ret = 0; 105 + 106 + switch (val) { 107 + case NFSD_IO_BUFFERED: 108 + case NFSD_IO_DONTCACHE: 109 + nfsd_io_cache_write = val; 110 + break; 111 + default: 112 + ret = -EINVAL; 113 + break; 114 + } 115 + 116 + return ret; 117 + } 118 + 119 + DEFINE_DEBUGFS_ATTRIBUTE(nfsd_io_cache_write_fops, nfsd_io_cache_write_get, 120 + nfsd_io_cache_write_set, "%llu\n"); 34 121 35 122 void nfsd_debugfs_exit(void) 36 123 { ··· 131 44 132 45 debugfs_create_file("disable-splice-read", S_IWUSR | S_IRUGO, 133 46 nfsd_top_dir, NULL, &nfsd_dsr_fops); 47 + 48 + debugfs_create_file("io_cache_read", 0644, nfsd_top_dir, NULL, 49 + &nfsd_io_cache_read_fops); 50 + 51 + debugfs_create_file("io_cache_write", 0644, nfsd_top_dir, NULL, 52 + &nfsd_io_cache_write_fops); 134 53 }
+57 -25
fs/nfsd/export.c
··· 1082 1082 } 1083 1083 1084 1084 /** 1085 - * check_nfsd_access - check if access to export is allowed. 1085 + * check_xprtsec_policy - check if access to export is allowed by the 1086 + * xprtsec policy 1086 1087 * @exp: svc_export that is being accessed. 1087 - * @rqstp: svc_rqst attempting to access @exp (will be NULL for LOCALIO). 1088 - * @may_bypass_gss: reduce strictness of authorization check 1088 + * @rqstp: svc_rqst attempting to access @exp. 1089 + * 1090 + * Helper function for check_nfsd_access(). Note that callers should be 1091 + * using check_nfsd_access() instead of calling this function directly. The 1092 + * one exception is __fh_verify() since it has logic that may result in one 1093 + * or both of the helpers being skipped. 1089 1094 * 1090 1095 * Return values: 1091 1096 * %nfs_ok if access is granted, or 1092 1097 * %nfserr_wrongsec if access is denied 1093 1098 */ 1094 - __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, 1095 - bool may_bypass_gss) 1099 + __be32 check_xprtsec_policy(struct svc_export *exp, struct svc_rqst *rqstp) 1096 1100 { 1097 - struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; 1098 - struct svc_xprt *xprt; 1099 - 1100 - /* 1101 - * If rqstp is NULL, this is a LOCALIO request which will only 1102 - * ever use a filehandle/credential pair for which access has 1103 - * been affirmed (by ACCESS or OPEN NFS requests) over the 1104 - * wire. So there is no need for further checks here. 1105 - */ 1106 - if (!rqstp) 1107 - return nfs_ok; 1108 - 1109 - xprt = rqstp->rq_xprt; 1101 + struct svc_xprt *xprt = rqstp->rq_xprt; 1110 1102 1111 1103 if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) { 1112 1104 if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags)) 1113 - goto ok; 1105 + return nfs_ok; 1114 1106 } 1115 1107 if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) { 1116 1108 if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) && 1117 1109 !test_bit(XPT_PEER_AUTH, &xprt->xpt_flags)) 1118 - goto ok; 1110 + return nfs_ok; 1119 1111 } 1120 1112 if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) { 1121 1113 if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) && 1122 1114 test_bit(XPT_PEER_AUTH, &xprt->xpt_flags)) 1123 - goto ok; 1115 + return nfs_ok; 1124 1116 } 1125 - if (!may_bypass_gss) 1126 - goto denied; 1117 + return nfserr_wrongsec; 1118 + } 1127 1119 1128 - ok: 1120 + /** 1121 + * check_security_flavor - check if access to export is allowed by the 1122 + * security flavor 1123 + * @exp: svc_export that is being accessed. 1124 + * @rqstp: svc_rqst attempting to access @exp. 1125 + * @may_bypass_gss: reduce strictness of authorization check 1126 + * 1127 + * Helper function for check_nfsd_access(). Note that callers should be 1128 + * using check_nfsd_access() instead of calling this function directly. The 1129 + * one exception is __fh_verify() since it has logic that may result in one 1130 + * or both of the helpers being skipped. 1131 + * 1132 + * Return values: 1133 + * %nfs_ok if access is granted, or 1134 + * %nfserr_wrongsec if access is denied 1135 + */ 1136 + __be32 check_security_flavor(struct svc_export *exp, struct svc_rqst *rqstp, 1137 + bool may_bypass_gss) 1138 + { 1139 + struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; 1140 + 1129 1141 /* legacy gss-only clients are always OK: */ 1130 1142 if (exp->ex_client == rqstp->rq_gssclient) 1131 1143 return nfs_ok; ··· 1179 1167 } 1180 1168 } 1181 1169 1182 - denied: 1183 1170 return nfserr_wrongsec; 1171 + } 1172 + 1173 + /** 1174 + * check_nfsd_access - check if access to export is allowed. 1175 + * @exp: svc_export that is being accessed. 1176 + * @rqstp: svc_rqst attempting to access @exp. 1177 + * @may_bypass_gss: reduce strictness of authorization check 1178 + * 1179 + * Return values: 1180 + * %nfs_ok if access is granted, or 1181 + * %nfserr_wrongsec if access is denied 1182 + */ 1183 + __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, 1184 + bool may_bypass_gss) 1185 + { 1186 + __be32 status; 1187 + 1188 + status = check_xprtsec_policy(exp, rqstp); 1189 + if (status != nfs_ok) 1190 + return status; 1191 + return check_security_flavor(exp, rqstp, may_bypass_gss); 1184 1192 } 1185 1193 1186 1194 /*
+3
fs/nfsd/export.h
··· 101 101 102 102 struct svc_cred; 103 103 int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp); 104 + __be32 check_xprtsec_policy(struct svc_export *exp, struct svc_rqst *rqstp); 105 + __be32 check_security_flavor(struct svc_export *exp, struct svc_rqst *rqstp, 106 + bool may_bypass_gss); 104 107 __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, 105 108 bool may_bypass_gss); 106 109
-21
fs/nfsd/filecache.c
··· 395 395 } 396 396 397 397 /** 398 - * nfsd_file_get_local - get nfsd_file reference and reference to net 399 - * @nf: nfsd_file of which to put the reference 400 - * 401 - * Get reference to both the nfsd_file and nf->nf_net. 402 - */ 403 - struct nfsd_file * 404 - nfsd_file_get_local(struct nfsd_file *nf) 405 - { 406 - struct net *net = nf->nf_net; 407 - 408 - if (nfsd_net_try_get(net)) { 409 - nf = nfsd_file_get(nf); 410 - if (!nf) 411 - nfsd_net_put(net); 412 - } else { 413 - nf = NULL; 414 - } 415 - return nf; 416 - } 417 - 418 - /** 419 398 * nfsd_file_file - get the backing file of an nfsd_file 420 399 * @nf: nfsd_file of which to access the backing file. 421 400 *
-1
fs/nfsd/filecache.h
··· 67 67 void nfsd_file_cache_shutdown_net(struct net *net); 68 68 void nfsd_file_put(struct nfsd_file *nf); 69 69 struct net *nfsd_file_put_local(struct nfsd_file __rcu **nf); 70 - struct nfsd_file *nfsd_file_get_local(struct nfsd_file *nf); 71 70 struct nfsd_file *nfsd_file_get(struct nfsd_file *nf); 72 71 struct file *nfsd_file_file(struct nfsd_file *nf); 73 72 void nfsd_file_close_inode_sync(struct inode *inode);
+2 -2
fs/nfsd/flexfilelayout.c
··· 20 20 #define NFSDDBG_FACILITY NFSDDBG_PNFS 21 21 22 22 static __be32 23 - nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, 24 - struct nfsd4_layoutget *args) 23 + nfsd4_ff_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode, 24 + const struct svc_fh *fhp, struct nfsd4_layoutget *args) 25 25 { 26 26 struct nfsd4_layout_seg *seg = &args->lg_seg; 27 27 u32 device_generation = 0;
+1 -2
fs/nfsd/flexfilelayoutxdr.c
··· 54 54 *p++ = cpu_to_be32(1); /* single mirror */ 55 55 *p++ = cpu_to_be32(1); /* single data server */ 56 56 57 - p = xdr_encode_opaque_fixed(p, &fl->deviceid, 58 - sizeof(struct nfsd4_deviceid)); 57 + p = svcxdr_encode_deviceid4(p, &fl->deviceid); 59 58 60 59 *p++ = cpu_to_be32(1); /* efficiency */ 61 60
-1
fs/nfsd/localio.c
··· 132 132 .nfsd_net_put = nfsd_net_put, 133 133 .nfsd_open_local_fh = nfsd_open_local_fh, 134 134 .nfsd_file_put_local = nfsd_file_put_local, 135 - .nfsd_file_get_local = nfsd_file_get_local, 136 135 .nfsd_file_file = nfsd_file_file, 137 136 .nfsd_file_dio_alignment = nfsd_file_dio_alignment, 138 137 };
+14 -1
fs/nfsd/lockd.c
··· 57 57 switch (nfserr) { 58 58 case nfs_ok: 59 59 return 0; 60 - case nfserr_dropit: 60 + case nfserr_jukebox: 61 + /* this error can indicate a presence of a conflicting 62 + * delegation to an NLM lock request. Options are: 63 + * (1) For now, drop this request and make the client 64 + * retry. When delegation is returned, client's lock retry 65 + * will complete. 66 + * (2) NLM4_DENIED as per "spec" signals to the client 67 + * that the lock is unavailable now but client can retry. 68 + * Linux client implementation does not. It treats 69 + * NLM4_DENIED same as NLM4_FAILED and errors the request. 70 + * (3) For the future, treat this as blocked lock and try 71 + * to callback when the delegation is returned but might 72 + * not have a proper lock request to block on. 73 + */ 61 74 return nlm_drop_reply; 62 75 case nfserr_stale: 63 76 return nlm_stale_fh;
-1
fs/nfsd/nfs4layouts.c
··· 120 120 121 121 id->fsid_idx = fhp->fh_export->ex_devid_map->idx; 122 122 id->generation = device_generation; 123 - id->pad = 0; 124 123 return 0; 125 124 } 126 125
+92 -35
fs/nfsd/nfs4proc.c
··· 1133 1133 exp_put(u->secinfo_no_name.sin_exp); 1134 1134 } 1135 1135 1136 + /* 1137 + * Validate that the requested timestamps are within the acceptable range. If 1138 + * timestamp appears to be in the future, then it will be clamped to 1139 + * current_time(). 1140 + */ 1141 + static void 1142 + vet_deleg_attrs(struct nfsd4_setattr *setattr, struct nfs4_delegation *dp) 1143 + { 1144 + struct timespec64 now = current_time(dp->dl_stid.sc_file->fi_inode); 1145 + struct iattr *iattr = &setattr->sa_iattr; 1146 + 1147 + if ((setattr->sa_bmval[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) && 1148 + !nfsd4_vet_deleg_time(&iattr->ia_atime, &dp->dl_atime, &now)) 1149 + iattr->ia_valid &= ~(ATTR_ATIME | ATTR_ATIME_SET); 1150 + 1151 + if (setattr->sa_bmval[2] & FATTR4_WORD2_TIME_DELEG_MODIFY) { 1152 + if (nfsd4_vet_deleg_time(&iattr->ia_mtime, &dp->dl_mtime, &now)) { 1153 + iattr->ia_ctime = iattr->ia_mtime; 1154 + if (nfsd4_vet_deleg_time(&iattr->ia_ctime, &dp->dl_ctime, &now)) 1155 + dp->dl_setattr = true; 1156 + else 1157 + iattr->ia_valid &= ~(ATTR_CTIME | ATTR_CTIME_SET); 1158 + } else { 1159 + iattr->ia_valid &= ~(ATTR_CTIME | ATTR_CTIME_SET | 1160 + ATTR_MTIME | ATTR_MTIME_SET); 1161 + } 1162 + } 1163 + } 1164 + 1136 1165 static __be32 1137 1166 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1138 1167 union nfsd4_op_u *u) ··· 1199 1170 struct nfs4_delegation *dp = delegstateid(st); 1200 1171 1201 1172 /* Only for *_ATTRS_DELEG flavors */ 1202 - if (deleg_attrs_deleg(dp->dl_type)) 1173 + if (deleg_attrs_deleg(dp->dl_type)) { 1174 + vet_deleg_attrs(setattr, dp); 1203 1175 status = nfs_ok; 1176 + } 1204 1177 } 1205 1178 } 1206 1179 if (st) ··· 1240 1209 return status; 1241 1210 } 1242 1211 1212 + static void nfsd4_file_mark_deleg_written(struct nfs4_file *fi) 1213 + { 1214 + spin_lock(&fi->fi_lock); 1215 + if (!list_empty(&fi->fi_delegations)) { 1216 + struct nfs4_delegation *dp = list_first_entry(&fi->fi_delegations, 1217 + struct nfs4_delegation, dl_perfile); 1218 + 1219 + if (dp->dl_type == OPEN_DELEGATE_WRITE_ATTRS_DELEG) 1220 + dp->dl_written = true; 1221 + } 1222 + spin_unlock(&fi->fi_lock); 1223 + } 1224 + 1243 1225 static __be32 1244 1226 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1245 1227 union nfsd4_op_u *u) 1246 1228 { 1247 1229 struct nfsd4_write *write = &u->write; 1248 1230 stateid_t *stateid = &write->wr_stateid; 1231 + struct nfs4_stid *stid = NULL; 1249 1232 struct nfsd_file *nf = NULL; 1250 1233 __be32 status = nfs_ok; 1251 1234 unsigned long cnt; ··· 1272 1227 trace_nfsd_write_start(rqstp, &cstate->current_fh, 1273 1228 write->wr_offset, cnt); 1274 1229 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh, 1275 - stateid, WR_STATE, &nf, NULL); 1230 + stateid, WR_STATE, &nf, &stid); 1276 1231 if (status) 1277 1232 return status; 1233 + 1234 + if (stid) { 1235 + nfsd4_file_mark_deleg_written(stid->sc_file); 1236 + nfs4_put_stid(stid); 1237 + } 1278 1238 1279 1239 write->wr_how_written = write->wr_stable_how; 1280 1240 status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf, ··· 1519 1469 return 0; 1520 1470 } 1521 1471 if (work) { 1522 - strscpy(work->nsui_ipaddr, ipaddr, sizeof(work->nsui_ipaddr) - 1); 1472 + strscpy(work->nsui_ipaddr, ipaddr, sizeof(work->nsui_ipaddr)); 1523 1473 refcount_set(&work->nsui_refcnt, 2); 1524 1474 work->nsui_busy = true; 1525 1475 list_add_tail(&work->nsui_list, &nn->nfsd_ssc_mount_list); ··· 2497 2447 if (atomic_read(&ls->ls_stid.sc_file->fi_lo_recalls)) 2498 2448 goto out_put_stid; 2499 2449 2500 - nfserr = ops->proc_layoutget(d_inode(current_fh->fh_dentry), 2450 + nfserr = ops->proc_layoutget(rqstp, d_inode(current_fh->fh_dentry), 2501 2451 current_fh, lgp); 2502 2452 if (nfserr) 2503 2453 goto out_put_stid; ··· 2521 2471 nfsd4_layoutcommit(struct svc_rqst *rqstp, 2522 2472 struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) 2523 2473 { 2474 + struct net *net = SVC_NET(rqstp); 2524 2475 struct nfsd4_layoutcommit *lcp = &u->layoutcommit; 2525 2476 const struct nfsd4_layout_seg *seg = &lcp->lc_seg; 2526 2477 struct svc_fh *current_fh = &cstate->current_fh; 2527 2478 const struct nfsd4_layout_ops *ops; 2528 - loff_t new_size = lcp->lc_last_wr + 1; 2529 2479 struct inode *inode; 2530 2480 struct nfs4_layout_stateid *ls; 2531 2481 __be32 nfserr; ··· 2541 2491 goto out; 2542 2492 inode = d_inode(current_fh->fh_dentry); 2543 2493 2544 - nfserr = nfserr_inval; 2545 - if (new_size <= seg->offset) { 2546 - dprintk("pnfsd: last write before layout segment\n"); 2547 - goto out; 2548 - } 2549 - if (new_size > seg->offset + seg->length) { 2550 - dprintk("pnfsd: last write beyond layout segment\n"); 2551 - goto out; 2552 - } 2553 - if (!lcp->lc_newoffset && new_size > i_size_read(inode)) { 2554 - dprintk("pnfsd: layoutcommit beyond EOF\n"); 2555 - goto out; 2494 + lcp->lc_size_chg = false; 2495 + if (lcp->lc_newoffset) { 2496 + loff_t new_size = lcp->lc_last_wr + 1; 2497 + 2498 + nfserr = nfserr_inval; 2499 + if (new_size <= seg->offset) 2500 + goto out; 2501 + if (new_size > seg->offset + seg->length) 2502 + goto out; 2503 + 2504 + if (new_size > i_size_read(inode)) { 2505 + lcp->lc_size_chg = true; 2506 + lcp->lc_newsize = new_size; 2507 + } 2556 2508 } 2557 2509 2558 - nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid, 2559 - false, lcp->lc_layout_type, 2560 - &ls); 2561 - if (nfserr) { 2562 - trace_nfsd_layout_commit_lookup_fail(&lcp->lc_sid); 2563 - /* fixup error code as per RFC5661 */ 2564 - if (nfserr == nfserr_bad_stateid) 2565 - nfserr = nfserr_badlayout; 2510 + nfserr = nfserr_grace; 2511 + if (locks_in_grace(net) && !lcp->lc_reclaim) 2566 2512 goto out; 2513 + nfserr = nfserr_no_grace; 2514 + if (!locks_in_grace(net) && lcp->lc_reclaim) 2515 + goto out; 2516 + 2517 + if (!lcp->lc_reclaim) { 2518 + nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, 2519 + &lcp->lc_sid, false, lcp->lc_layout_type, &ls); 2520 + if (nfserr) { 2521 + trace_nfsd_layout_commit_lookup_fail(&lcp->lc_sid); 2522 + /* fixup error code as per RFC5661 */ 2523 + if (nfserr == nfserr_bad_stateid) 2524 + nfserr = nfserr_badlayout; 2525 + goto out; 2526 + } 2527 + 2528 + /* LAYOUTCOMMIT does not require any serialization */ 2529 + mutex_unlock(&ls->ls_mutex); 2567 2530 } 2568 2531 2569 - /* LAYOUTCOMMIT does not require any serialization */ 2570 - mutex_unlock(&ls->ls_mutex); 2532 + nfserr = ops->proc_layoutcommit(inode, rqstp, lcp); 2571 2533 2572 - if (new_size > i_size_read(inode)) { 2573 - lcp->lc_size_chg = true; 2574 - lcp->lc_newsize = new_size; 2575 - } else { 2576 - lcp->lc_size_chg = false; 2534 + if (!lcp->lc_reclaim) { 2535 + nfsd4_file_mark_deleg_written(ls->ls_stid.sc_file); 2536 + nfs4_put_stid(&ls->ls_stid); 2577 2537 } 2578 - 2579 - nfserr = ops->proc_layoutcommit(inode, lcp); 2580 - nfs4_put_stid(&ls->ls_stid); 2581 2538 out: 2582 2539 return nfserr; 2583 2540 }
+5 -26
fs/nfsd/nfs4recover.c
··· 92 92 put_cred(revert_creds(original)); 93 93 } 94 94 95 - static void 96 - md5_to_hex(char *out, char *md5) 97 - { 98 - int i; 99 - 100 - for (i=0; i<16; i++) { 101 - unsigned char c = md5[i]; 102 - 103 - *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); 104 - *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); 105 - } 106 - *out = '\0'; 107 - } 108 - 109 95 static int 110 - nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname) 96 + nfs4_make_rec_clidname(char dname[HEXDIR_LEN], const struct xdr_netobj *clname) 111 97 { 112 - struct xdr_netobj cksum; 98 + u8 digest[MD5_DIGEST_SIZE]; 113 99 struct crypto_shash *tfm; 114 100 int status; 115 101 ··· 107 121 goto out_no_tfm; 108 122 } 109 123 110 - cksum.len = crypto_shash_digestsize(tfm); 111 - cksum.data = kmalloc(cksum.len, GFP_KERNEL); 112 - if (cksum.data == NULL) { 113 - status = -ENOMEM; 114 - goto out; 115 - } 116 - 117 124 status = crypto_shash_tfm_digest(tfm, clname->data, clname->len, 118 - cksum.data); 125 + digest); 119 126 if (status) 120 127 goto out; 121 128 122 - md5_to_hex(dname, cksum.data); 129 + static_assert(HEXDIR_LEN == 2 * MD5_DIGEST_SIZE + 1); 130 + sprintf(dname, "%*phN", MD5_DIGEST_SIZE, digest); 123 131 124 132 status = 0; 125 133 out: 126 - kfree(cksum.data); 127 134 crypto_free_shash(tfm); 128 135 out_no_tfm: 129 136 return status;
+65 -21
fs/nfsd/nfs4state.c
··· 1222 1222 nfs4_file_put_access(fp, NFS4_SHARE_ACCESS_READ); 1223 1223 } 1224 1224 1225 + static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f) 1226 + { 1227 + struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME }; 1228 + struct inode *inode = file_inode(f); 1229 + int ret; 1230 + 1231 + /* don't do anything if FMODE_NOCMTIME isn't set */ 1232 + if ((READ_ONCE(f->f_mode) & FMODE_NOCMTIME) == 0) 1233 + return; 1234 + 1235 + spin_lock(&f->f_lock); 1236 + f->f_mode &= ~FMODE_NOCMTIME; 1237 + spin_unlock(&f->f_lock); 1238 + 1239 + /* was it never written? */ 1240 + if (!dp->dl_written) 1241 + return; 1242 + 1243 + /* did it get a setattr for the timestamps at some point? */ 1244 + if (dp->dl_setattr) 1245 + return; 1246 + 1247 + /* Stamp everything to "now" */ 1248 + inode_lock(inode); 1249 + ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &ia, NULL); 1250 + inode_unlock(inode); 1251 + if (ret) { 1252 + struct inode *inode = file_inode(f); 1253 + 1254 + pr_notice_ratelimited("Unable to update timestamps on inode %02x:%02x:%lu: %d\n", 1255 + MAJOR(inode->i_sb->s_dev), 1256 + MINOR(inode->i_sb->s_dev), 1257 + inode->i_ino, ret); 1258 + } 1259 + } 1260 + 1225 1261 static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp) 1226 1262 { 1227 1263 struct nfs4_file *fp = dp->dl_stid.sc_file; ··· 1265 1229 1266 1230 WARN_ON_ONCE(!fp->fi_delegees); 1267 1231 1232 + nfsd4_finalize_deleg_timestamps(dp, nf->nf_file); 1268 1233 kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp); 1269 1234 put_deleg_file(fp); 1270 1235 } ··· 6194 6157 path.dentry = file_dentry(nf->nf_file); 6195 6158 6196 6159 rc = vfs_getattr(&path, stat, 6197 - (STATX_MODE | STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE), 6160 + STATX_MODE | STATX_SIZE | STATX_ATIME | 6161 + STATX_MTIME | STATX_CTIME | STATX_CHANGE_COOKIE, 6198 6162 AT_STATX_SYNC_AS_STAT); 6199 6163 6200 6164 nfsd_file_put(nf); ··· 6302 6264 memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid)); 6303 6265 6304 6266 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) { 6267 + struct file *f = dp->dl_stid.sc_file->fi_deleg_file->nf_file; 6268 + 6305 6269 if (!nfsd4_add_rdaccess_to_wrdeleg(rqstp, open, fh, stp) || 6306 6270 !nfs4_delegation_stat(dp, currentfh, &stat)) { 6307 6271 nfs4_put_stid(&dp->dl_stid); ··· 6314 6274 OPEN_DELEGATE_WRITE; 6315 6275 dp->dl_cb_fattr.ncf_cur_fsize = stat.size; 6316 6276 dp->dl_cb_fattr.ncf_initial_cinfo = nfsd4_change_attribute(&stat); 6277 + dp->dl_atime = stat.atime; 6278 + dp->dl_ctime = stat.ctime; 6279 + dp->dl_mtime = stat.mtime; 6280 + spin_lock(&f->f_lock); 6281 + f->f_mode |= FMODE_NOCMTIME; 6282 + spin_unlock(&f->f_lock); 6317 6283 trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid); 6318 6284 } else { 6319 - open->op_delegate_type = deleg_ts ? OPEN_DELEGATE_READ_ATTRS_DELEG : 6320 - OPEN_DELEGATE_READ; 6285 + open->op_delegate_type = deleg_ts && nfs4_delegation_stat(dp, currentfh, &stat) ? 6286 + OPEN_DELEGATE_READ_ATTRS_DELEG : OPEN_DELEGATE_READ; 6287 + dp->dl_atime = stat.atime; 6321 6288 trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid); 6322 6289 } 6323 6290 nfs4_put_stid(&dp->dl_stid); ··· 9177 9130 } 9178 9131 9179 9132 /** 9180 - * set_cb_time - vet and set the timespec for a cb_getattr update 9181 - * @cb: timestamp from the CB_GETATTR response 9133 + * nfsd4_vet_deleg_time - vet and set the timespec for a delegated timestamp update 9134 + * @req: timestamp from the client 9182 9135 * @orig: original timestamp in the inode 9183 9136 * @now: current time 9184 9137 * 9185 - * Given a timestamp in a CB_GETATTR response, check it against the 9138 + * Given a timestamp from the client response, check it against the 9186 9139 * current timestamp in the inode and the current time. Returns true 9187 9140 * if the inode's timestamp needs to be updated, and false otherwise. 9188 - * @cb may also be changed if the timestamp needs to be clamped. 9141 + * @req may also be changed if the timestamp needs to be clamped. 9189 9142 */ 9190 - static bool set_cb_time(struct timespec64 *cb, const struct timespec64 *orig, 9191 - const struct timespec64 *now) 9143 + bool nfsd4_vet_deleg_time(struct timespec64 *req, const struct timespec64 *orig, 9144 + const struct timespec64 *now) 9192 9145 { 9193 9146 9194 9147 /* 9195 9148 * "When the time presented is before the original time, then the 9196 9149 * update is ignored." Also no need to update if there is no change. 9197 9150 */ 9198 - if (timespec64_compare(cb, orig) <= 0) 9151 + if (timespec64_compare(req, orig) <= 0) 9199 9152 return false; 9200 9153 9201 9154 /* ··· 9203 9156 * clamp the new time to the current time, or it may 9204 9157 * return NFS4ERR_DELAY to the client, allowing it to retry." 9205 9158 */ 9206 - if (timespec64_compare(cb, now) > 0) { 9207 - /* clamp it */ 9208 - *cb = *now; 9209 - } 9159 + if (timespec64_compare(req, now) > 0) 9160 + *req = *now; 9210 9161 9211 9162 return true; 9212 9163 } ··· 9212 9167 static int cb_getattr_update_times(struct dentry *dentry, struct nfs4_delegation *dp) 9213 9168 { 9214 9169 struct inode *inode = d_inode(dentry); 9215 - struct timespec64 now = current_time(inode); 9216 9170 struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; 9217 9171 struct iattr attrs = { }; 9218 9172 int ret; 9219 9173 9220 9174 if (deleg_attrs_deleg(dp->dl_type)) { 9221 - struct timespec64 atime = inode_get_atime(inode); 9222 - struct timespec64 mtime = inode_get_mtime(inode); 9175 + struct timespec64 now = current_time(inode); 9223 9176 9224 9177 attrs.ia_atime = ncf->ncf_cb_atime; 9225 9178 attrs.ia_mtime = ncf->ncf_cb_mtime; 9226 9179 9227 - if (set_cb_time(&attrs.ia_atime, &atime, &now)) 9180 + if (nfsd4_vet_deleg_time(&attrs.ia_atime, &dp->dl_atime, &now)) 9228 9181 attrs.ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 9229 9182 9230 - if (set_cb_time(&attrs.ia_mtime, &mtime, &now)) { 9231 - attrs.ia_valid |= ATTR_CTIME | ATTR_MTIME | ATTR_MTIME_SET; 9183 + if (nfsd4_vet_deleg_time(&attrs.ia_mtime, &dp->dl_mtime, &now)) { 9184 + attrs.ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; 9232 9185 attrs.ia_ctime = attrs.ia_mtime; 9186 + if (nfsd4_vet_deleg_time(&attrs.ia_ctime, &dp->dl_ctime, &now)) 9187 + attrs.ia_valid |= ATTR_CTIME | ATTR_CTIME_SET; 9233 9188 } 9234 9189 } else { 9235 9190 attrs.ia_valid |= ATTR_MTIME | ATTR_CTIME; 9236 - attrs.ia_mtime = attrs.ia_ctime = now; 9237 9191 } 9238 9192 9239 9193 if (!attrs.ia_valid)
+10 -22
fs/nfsd/nfs4xdr.c
··· 538 538 iattr->ia_mtime.tv_sec = modify.seconds; 539 539 iattr->ia_mtime.tv_nsec = modify.nseconds; 540 540 iattr->ia_ctime.tv_sec = modify.seconds; 541 - iattr->ia_ctime.tv_nsec = modify.seconds; 542 - iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME | ATTR_MTIME_SET | ATTR_DELEG; 541 + iattr->ia_ctime.tv_nsec = modify.nseconds; 542 + iattr->ia_valid |= ATTR_CTIME | ATTR_CTIME_SET | 543 + ATTR_MTIME | ATTR_MTIME_SET | ATTR_DELEG; 543 544 } 544 545 545 546 /* request sanity: did attrlist4 contain the expected number of words? */ ··· 588 587 } 589 588 590 589 #ifdef CONFIG_NFSD_PNFS 591 - static __be32 592 - nfsd4_decode_deviceid4(struct nfsd4_compoundargs *argp, 593 - struct nfsd4_deviceid *devid) 594 - { 595 - __be32 *p; 596 - 597 - p = xdr_inline_decode(argp->xdr, NFS4_DEVICEID4_SIZE); 598 - if (!p) 599 - return nfserr_bad_xdr; 600 - memcpy(devid, p, sizeof(*devid)); 601 - return nfs_ok; 602 - } 603 590 604 591 static __be32 605 592 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp, 606 593 struct nfsd4_layoutcommit *lcp) 607 594 { 595 + u32 len; 596 + 608 597 if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_layout_type) < 0) 609 598 return nfserr_bad_xdr; 610 599 if (lcp->lc_layout_type < LAYOUT_NFSV4_1_FILES) ··· 602 611 if (lcp->lc_layout_type >= LAYOUT_TYPE_MAX) 603 612 return nfserr_bad_xdr; 604 613 605 - if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_up_len) < 0) 614 + if (xdr_stream_decode_u32(argp->xdr, &len) < 0) 606 615 return nfserr_bad_xdr; 607 - if (lcp->lc_up_len > 0) { 608 - lcp->lc_up_layout = xdr_inline_decode(argp->xdr, lcp->lc_up_len); 609 - if (!lcp->lc_up_layout) 610 - return nfserr_bad_xdr; 611 - } 616 + if (!xdr_stream_subsegment(argp->xdr, &lcp->lc_up_layout, len)) 617 + return nfserr_bad_xdr; 612 618 613 619 return nfs_ok; 614 620 } ··· 1771 1783 __be32 status; 1772 1784 1773 1785 memset(gdev, 0, sizeof(*gdev)); 1774 - status = nfsd4_decode_deviceid4(argp, &gdev->gd_devid); 1786 + status = nfsd4_decode_deviceid4(argp->xdr, &gdev->gd_devid); 1775 1787 if (status) 1776 1788 return status; 1777 1789 if (xdr_stream_decode_u32(argp->xdr, &gdev->gd_layout_type) < 0) ··· 1802 1814 status = nfsd4_decode_stateid4(argp, &lcp->lc_sid); 1803 1815 if (status) 1804 1816 return status; 1805 - if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_newoffset) < 0) 1817 + if (xdr_stream_decode_bool(argp->xdr, &lcp->lc_newoffset) < 0) 1806 1818 return nfserr_bad_xdr; 1807 1819 if (lcp->lc_newoffset) { 1808 1820 if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_last_wr) < 0)
+1 -14
fs/nfsd/nfscache.c
··· 27 27 * cache size, the idea being that when the cache is at its maximum number 28 28 * of entries, then this should be the average number of entries per bucket. 29 29 */ 30 - #define TARGET_BUCKET_SIZE 64 30 + #define TARGET_BUCKET_SIZE 8 31 31 32 32 struct nfsd_drc_bucket { 33 33 struct rb_root rb_head; ··· 237 237 238 238 } 239 239 240 - /* 241 - * Move cache entry to end of LRU list, and queue the cleaner to run if it's 242 - * not already scheduled. 243 - */ 244 240 static void 245 241 lru_put_end(struct nfsd_drc_bucket *b, struct nfsd_cacherep *rp) 246 242 { ··· 268 272 269 273 /* The bucket LRU is ordered oldest-first. */ 270 274 list_for_each_entry_safe(rp, tmp, &b->lru_head, c_lru) { 271 - /* 272 - * Don't free entries attached to calls that are still 273 - * in-progress, but do keep scanning the list. 274 - */ 275 - if (rp->c_state == RC_INPROG) 276 - continue; 277 - 278 275 if (atomic_read(&nn->num_drc_entries) <= nn->max_drc_entries && 279 276 time_before(expiry, rp->c_timestamp)) 280 277 break; ··· 442 453 nn->longest_chain_cachesize, 443 454 atomic_read(&nn->num_drc_entries)); 444 455 } 445 - 446 - lru_put_end(b, ret); 447 456 return ret; 448 457 } 449 458
+10 -7
fs/nfsd/nfsd.h
··· 153 153 154 154 extern bool nfsd_disable_splice_read __read_mostly; 155 155 156 + enum { 157 + /* Any new NFSD_IO enum value must be added at the end */ 158 + NFSD_IO_BUFFERED, 159 + NFSD_IO_DONTCACHE, 160 + }; 161 + 162 + extern u64 nfsd_io_cache_read __read_mostly; 163 + extern u64 nfsd_io_cache_write __read_mostly; 164 + 156 165 extern int nfsd_max_blksize; 157 166 158 167 static inline int nfsd_v4client(struct svc_rqst *rq) ··· 344 335 * cannot conflict with any existing be32 nfserr value. 345 336 */ 346 337 enum { 347 - NFSERR_DROPIT = NFS4ERR_FIRST_FREE, 348 - /* if a request fails due to kmalloc failure, it gets dropped. 349 - * Client should resend eventually 350 - */ 351 - #define nfserr_dropit cpu_to_be32(NFSERR_DROPIT) 352 - 353 338 /* end-of-file indicator in readdir */ 354 - NFSERR_EOF, 339 + NFSERR_EOF = NFS4ERR_FIRST_FREE, 355 340 #define nfserr_eof cpu_to_be32(NFSERR_EOF) 356 341 357 342 /* replay detected */
+51 -4
fs/nfsd/nfsfh.c
··· 364 364 if (error) 365 365 goto out; 366 366 367 + /* 368 + * If rqstp is NULL, this is a LOCALIO request which will only 369 + * ever use a filehandle/credential pair for which access has 370 + * been affirmed (by ACCESS or OPEN NFS requests) over the 371 + * wire. Skip both the xprtsec policy and the security flavor 372 + * checks. 373 + */ 374 + if (!rqstp) 375 + goto check_permissions; 376 + 367 377 if ((access & NFSD_MAY_NLM) && (exp->ex_flags & NFSEXP_NOAUTHNLM)) 368 378 /* NLM is allowed to fully bypass authentication */ 369 379 goto out; 380 + 381 + /* 382 + * NLM is allowed to bypass the xprtsec policy check because lockd 383 + * doesn't support xprtsec. 384 + */ 385 + if (!(access & NFSD_MAY_NLM)) { 386 + error = check_xprtsec_policy(exp, rqstp); 387 + if (error) 388 + goto out; 389 + } 370 390 371 391 if (access & NFSD_MAY_BYPASS_GSS) 372 392 may_bypass_gss = true; ··· 399 379 && exp->ex_path.dentry == dentry) 400 380 may_bypass_gss = true; 401 381 402 - error = check_nfsd_access(exp, rqstp, may_bypass_gss); 382 + error = check_security_flavor(exp, rqstp, may_bypass_gss); 403 383 if (error) 404 384 goto out; 405 - /* During LOCALIO call to fh_verify will be called with a NULL rqstp */ 406 - if (rqstp) 407 - svc_xprt_set_valid(rqstp->rq_xprt); 408 385 386 + svc_xprt_set_valid(rqstp->rq_xprt); 387 + 388 + check_permissions: 409 389 /* Finally, check access permissions. */ 410 390 error = nfsd_permission(cred, exp, dentry, access); 411 391 out: ··· 680 660 printk(KERN_ERR "fh_update: %pd2 still negative!\n", 681 661 dentry); 682 662 return nfserr_serverfault; 663 + } 664 + 665 + /** 666 + * fh_getattr - Retrieve attributes on a local file 667 + * @fhp: File handle of target file 668 + * @stat: Caller-supplied kstat buffer to be filled in 669 + * 670 + * Returns nfs_ok on success, otherwise an NFS status code is 671 + * returned. 672 + */ 673 + __be32 fh_getattr(const struct svc_fh *fhp, struct kstat *stat) 674 + { 675 + struct path p = { 676 + .mnt = fhp->fh_export->ex_path.mnt, 677 + .dentry = fhp->fh_dentry, 678 + }; 679 + struct inode *inode = d_inode(p.dentry); 680 + u32 request_mask = STATX_BASIC_STATS; 681 + 682 + if (S_ISREG(inode->i_mode)) 683 + request_mask |= (STATX_DIOALIGN | STATX_DIO_READ_ALIGN); 684 + 685 + if (fhp->fh_maxsize == NFS4_FHSIZE) 686 + request_mask |= (STATX_BTIME | STATX_CHANGE_COOKIE); 687 + 688 + return nfserrno(vfs_getattr(&p, stat, request_mask, 689 + AT_STATX_SYNC_AS_STAT)); 683 690 } 684 691 685 692 /**
+38
fs/nfsd/nfsfh.h
··· 14 14 #include <linux/exportfs.h> 15 15 #include <linux/nfs4.h> 16 16 17 + #include "export.h" 18 + 17 19 /* 18 20 * The file handle starts with a sequence of four-byte words. 19 21 * The first word contains a version number (1) and three descriptor bytes ··· 222 220 __be32 fh_verify(struct svc_rqst *, struct svc_fh *, umode_t, int); 223 221 __be32 fh_verify_local(struct net *, struct svc_cred *, struct auth_domain *, 224 222 struct svc_fh *, umode_t, int); 223 + __be32 fh_getattr(const struct svc_fh *fhp, struct kstat *stat); 225 224 __be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); 226 225 __be32 fh_update(struct svc_fh *); 227 226 void fh_put(struct svc_fh *); ··· 272 269 if (memcmp(fsid1, fsid2, key_len(fh1->fh_fsid_type)) != 0) 273 270 return false; 274 271 return true; 272 + } 273 + 274 + /** 275 + * fh_want_write - Get write access to an export 276 + * @fhp: File handle of file to be written 277 + * 278 + * Caller must invoke fh_drop_write() when its write operation 279 + * is complete. 280 + * 281 + * Returns 0 if the file handle's export can be written to. Otherwise 282 + * the export is not prepared for updates, and the returned negative 283 + * errno value reflects the reason for the failure. 284 + */ 285 + static inline int fh_want_write(struct svc_fh *fhp) 286 + { 287 + int ret; 288 + 289 + if (fhp->fh_want_write) 290 + return 0; 291 + ret = mnt_want_write(fhp->fh_export->ex_path.mnt); 292 + if (!ret) 293 + fhp->fh_want_write = true; 294 + return ret; 295 + } 296 + 297 + /** 298 + * fh_drop_write - Release write access on an export 299 + * @fhp: File handle of file on which fh_want_write() was previously called 300 + */ 301 + static inline void fh_drop_write(struct svc_fh *fhp) 302 + { 303 + if (fhp->fh_want_write) { 304 + fhp->fh_want_write = false; 305 + mnt_drop_write(fhp->fh_export->ex_path.mnt); 306 + } 275 307 } 276 308 277 309 /**
+3 -2
fs/nfsd/pnfs.h
··· 29 29 __be32 (*encode_getdeviceinfo)(struct xdr_stream *xdr, 30 30 const struct nfsd4_getdeviceinfo *gdevp); 31 31 32 - __be32 (*proc_layoutget)(struct inode *, const struct svc_fh *fhp, 33 - struct nfsd4_layoutget *lgp); 32 + __be32 (*proc_layoutget)(struct svc_rqst *rqstp, struct inode *inode, 33 + const struct svc_fh *fhp, struct nfsd4_layoutget *lgp); 34 34 __be32 (*encode_layoutget)(struct xdr_stream *xdr, 35 35 const struct nfsd4_layoutget *lgp); 36 36 37 37 __be32 (*proc_layoutcommit)(struct inode *inode, 38 + struct svc_rqst *rqstp, 38 39 struct nfsd4_layoutcommit *lcp); 39 40 40 41 void (*fence_client)(struct nfs4_layout_stateid *ls,
+14 -2
fs/nfsd/state.h
··· 35 35 #ifndef _NFSD4_STATE_H 36 36 #define _NFSD4_STATE_H 37 37 38 + #include <crypto/md5.h> 38 39 #include <linux/idr.h> 39 40 #include <linux/refcount.h> 40 41 #include <linux/sunrpc/svc_xprt.h> ··· 218 217 struct nfs4_clnt_odstate *dl_clnt_odstate; 219 218 time64_t dl_time; 220 219 u32 dl_type; 221 - /* For recall: */ 220 + /* For recall: */ 222 221 int dl_retries; 223 222 struct nfsd4_callback dl_recall; 224 223 bool dl_recalled; 224 + bool dl_written; 225 + bool dl_setattr; 225 226 226 227 /* for CB_GETATTR */ 227 228 struct nfs4_cb_fattr dl_cb_fattr; 229 + 230 + /* For delegated timestamps */ 231 + struct timespec64 dl_atime; 232 + struct timespec64 dl_mtime; 233 + struct timespec64 dl_ctime; 228 234 }; 229 235 230 236 static inline bool deleg_is_read(u32 dl_type) ··· 249 241 return dl_type == OPEN_DELEGATE_READ_ATTRS_DELEG || 250 242 dl_type == OPEN_DELEGATE_WRITE_ATTRS_DELEG; 251 243 } 244 + 245 + bool nfsd4_vet_deleg_time(struct timespec64 *cb, const struct timespec64 *orig, 246 + const struct timespec64 *now); 252 247 253 248 #define cb_to_delegation(cb) \ 254 249 container_of(cb, struct nfs4_delegation, dl_recall) ··· 392 381 u32 reserved; 393 382 }; 394 383 395 - #define HEXDIR_LEN 33 /* hex version of 16 byte md5 of cl_name plus '\0' */ 384 + /* Length of MD5 digest as hex, plus terminating '\0' */ 385 + #define HEXDIR_LEN (2 * MD5_DIGEST_SIZE + 1) 396 386 397 387 /* 398 388 * State Meaning Where set
+22 -1
fs/nfsd/vfs.c
··· 49 49 #define NFSDDBG_FACILITY NFSDDBG_FILEOP 50 50 51 51 bool nfsd_disable_splice_read __read_mostly; 52 + u64 nfsd_io_cache_read __read_mostly = NFSD_IO_BUFFERED; 53 + u64 nfsd_io_cache_write __read_mostly = NFSD_IO_BUFFERED; 52 54 53 55 /** 54 56 * nfserrno - Map Linux errnos to NFS errnos ··· 469 467 return 0; 470 468 } 471 469 472 - if (!iap->ia_valid) 470 + if ((iap->ia_valid & ~ATTR_DELEG) == 0) 473 471 return 0; 474 472 475 473 /* ··· 1101 1099 size_t len; 1102 1100 1103 1101 init_sync_kiocb(&kiocb, file); 1102 + 1103 + switch (nfsd_io_cache_read) { 1104 + case NFSD_IO_BUFFERED: 1105 + break; 1106 + case NFSD_IO_DONTCACHE: 1107 + if (file->f_op->fop_flags & FOP_DONTCACHE) 1108 + kiocb.ki_flags = IOCB_DONTCACHE; 1109 + break; 1110 + } 1111 + 1104 1112 kiocb.ki_pos = offset; 1105 1113 1106 1114 v = 0; ··· 1236 1224 since = READ_ONCE(file->f_wb_err); 1237 1225 if (verf) 1238 1226 nfsd_copy_write_verifier(verf, nn); 1227 + 1228 + switch (nfsd_io_cache_write) { 1229 + case NFSD_IO_BUFFERED: 1230 + break; 1231 + case NFSD_IO_DONTCACHE: 1232 + if (file->f_op->fop_flags & FOP_DONTCACHE) 1233 + kiocb.ki_flags |= IOCB_DONTCACHE; 1234 + break; 1235 + } 1239 1236 host_err = vfs_iocb_iter_write(file, &kiocb, &iter); 1240 1237 if (host_err < 0) { 1241 1238 commit_reset_write_verifier(nn, rqstp, host_err);
-37
fs/nfsd/vfs.h
··· 160 160 161 161 void nfsd_filp_close(struct file *fp); 162 162 163 - static inline int fh_want_write(struct svc_fh *fh) 164 - { 165 - int ret; 166 - 167 - if (fh->fh_want_write) 168 - return 0; 169 - ret = mnt_want_write(fh->fh_export->ex_path.mnt); 170 - if (!ret) 171 - fh->fh_want_write = true; 172 - return ret; 173 - } 174 - 175 - static inline void fh_drop_write(struct svc_fh *fh) 176 - { 177 - if (fh->fh_want_write) { 178 - fh->fh_want_write = false; 179 - mnt_drop_write(fh->fh_export->ex_path.mnt); 180 - } 181 - } 182 - 183 - static inline __be32 fh_getattr(const struct svc_fh *fh, struct kstat *stat) 184 - { 185 - u32 request_mask = STATX_BASIC_STATS; 186 - struct path p = {.mnt = fh->fh_export->ex_path.mnt, 187 - .dentry = fh->fh_dentry}; 188 - struct inode *inode = d_inode(p.dentry); 189 - 190 - if (S_ISREG(inode->i_mode)) 191 - request_mask |= (STATX_DIOALIGN | STATX_DIO_READ_ALIGN); 192 - 193 - if (fh->fh_maxsize == NFS4_FHSIZE) 194 - request_mask |= (STATX_BTIME | STATX_CHANGE_COOKIE); 195 - 196 - return nfserrno(vfs_getattr(&p, stat, request_mask, 197 - AT_STATX_SYNC_AS_STAT)); 198 - } 199 - 200 163 #endif /* LINUX_NFSD_VFS_H */
+36 -3
fs/nfsd/xdr4.h
··· 595 595 struct nfsd4_deviceid { 596 596 u64 fsid_idx; 597 597 u32 generation; 598 - u32 pad; 599 598 }; 599 + 600 + static inline __be32 * 601 + svcxdr_encode_deviceid4(__be32 *p, const struct nfsd4_deviceid *devid) 602 + { 603 + __be64 *q = (__be64 *)p; 604 + 605 + *q = (__force __be64)devid->fsid_idx; 606 + p += 2; 607 + *p++ = (__force __be32)devid->generation; 608 + *p++ = xdr_zero; 609 + return p; 610 + } 611 + 612 + static inline __be32 * 613 + svcxdr_decode_deviceid4(__be32 *p, struct nfsd4_deviceid *devid) 614 + { 615 + __be64 *q = (__be64 *)p; 616 + 617 + devid->fsid_idx = (__force u64)(*q); 618 + p += 2; 619 + devid->generation = (__force u32)(*p++); 620 + p++; /* NFSD does not use the remaining octets */ 621 + return p; 622 + } 623 + 624 + static inline __be32 625 + nfsd4_decode_deviceid4(struct xdr_stream *xdr, struct nfsd4_deviceid *devid) 626 + { 627 + __be32 *p = xdr_inline_decode(xdr, NFS4_DEVICEID4_SIZE); 628 + 629 + if (unlikely(!p)) 630 + return nfserr_bad_xdr; 631 + svcxdr_decode_deviceid4(p, devid); 632 + return nfs_ok; 633 + } 600 634 601 635 struct nfsd4_layout_seg { 602 636 u32 iomode; ··· 664 630 u64 lc_last_wr; /* request */ 665 631 struct timespec64 lc_mtime; /* request */ 666 632 u32 lc_layout_type; /* request */ 667 - u32 lc_up_len; /* layout length */ 668 - void *lc_up_layout; /* decoded by callback */ 633 + struct xdr_buf lc_up_layout; /* decoded by callback */ 669 634 bool lc_size_chg; /* response */ 670 635 u64 lc_newsize; /* response */ 671 636 };
+1
include/linux/fs.h
··· 236 236 #define ATTR_ATIME_SET (1 << 7) 237 237 #define ATTR_MTIME_SET (1 << 8) 238 238 #define ATTR_FORCE (1 << 9) /* Not a change, but a change it */ 239 + #define ATTR_CTIME_SET (1 << 10) 239 240 #define ATTR_KILL_SUID (1 << 11) 240 241 #define ATTR_KILL_SGID (1 << 12) 241 242 #define ATTR_FILE (1 << 13)
-1
include/linux/nfslocalio.h
··· 63 63 struct nfsd_file __rcu **pnf, 64 64 const fmode_t); 65 65 struct net *(*nfsd_file_put_local)(struct nfsd_file __rcu **); 66 - struct nfsd_file *(*nfsd_file_get_local)(struct nfsd_file *); 67 66 struct file *(*nfsd_file_file)(struct nfsd_file *); 68 67 void (*nfsd_file_dio_alignment)(struct nfsd_file *, 69 68 u32 *, u32 *, u32 *);
+3
include/linux/sunrpc/svc_xprt.h
··· 104 104 * it has access to. It is NOT counted 105 105 * in ->sv_tmpcnt. 106 106 */ 107 + XPT_RPCB_UNREG, /* transport that needs unregistering 108 + * with rpcbind (TCP, UDP) on destroy 109 + */ 107 110 }; 108 111 109 112 /*
+2 -2
include/linux/sunrpc/xdr.h
··· 721 721 * @len: size of buffer pointed to by @ptr 722 722 * 723 723 * Return values: 724 - * On success, returns size of object stored in @ptr 724 + * %0 on success 725 725 * %-EBADMSG on XDR buffer overflow 726 726 */ 727 727 static inline ssize_t ··· 732 732 if (unlikely(!p)) 733 733 return -EBADMSG; 734 734 xdr_decode_opaque_fixed(p, ptr, len); 735 - return len; 735 + return 0; 736 736 } 737 737 738 738 /**
+2 -1
net/sunrpc/Kconfig
··· 18 18 19 19 config RPCSEC_GSS_KRB5 20 20 tristate "Secure RPC: Kerberos V mechanism" 21 - depends on SUNRPC && CRYPTO 21 + depends on SUNRPC 22 22 default y 23 23 select SUNRPC_GSS 24 + select CRYPTO 24 25 select CRYPTO_SKCIPHER 25 26 select CRYPTO_HASH 26 27 help
+1 -1
net/sunrpc/auth_gss/svcauth_gss.c
··· 724 724 rqstp->rq_auth_stat = rpc_autherr_badverf; 725 725 return SVC_DENIED; 726 726 } 727 - if (flavor != RPC_AUTH_GSS) { 727 + if (flavor != RPC_AUTH_GSS || checksum.len < XDR_UNIT) { 728 728 rqstp->rq_auth_stat = rpc_autherr_badverf; 729 729 return SVC_DENIED; 730 730 }
+14 -3
net/sunrpc/svc.c
··· 1425 1425 1426 1426 /* Call the function that processes the request. */ 1427 1427 rc = process.dispatch(rqstp); 1428 - if (procp->pc_release) 1429 - procp->pc_release(rqstp); 1430 1428 xdr_finish_decode(xdr); 1431 1429 1432 1430 if (!rc) ··· 1523 1525 trace_svc_drop(rqstp); 1524 1526 } 1525 1527 1528 + static void svc_release_rqst(struct svc_rqst *rqstp) 1529 + { 1530 + const struct svc_procedure *procp = rqstp->rq_procinfo; 1531 + 1532 + if (procp && procp->pc_release) 1533 + procp->pc_release(rqstp); 1534 + } 1535 + 1526 1536 /** 1527 1537 * svc_process - Execute one RPC transaction 1528 1538 * @rqstp: RPC transaction context ··· 1570 1564 if (unlikely(*p != rpc_call)) 1571 1565 goto out_baddir; 1572 1566 1573 - if (!svc_process_common(rqstp)) 1567 + if (!svc_process_common(rqstp)) { 1568 + svc_release_rqst(rqstp); 1574 1569 goto out_drop; 1570 + } 1575 1571 svc_send(rqstp); 1572 + svc_release_rqst(rqstp); 1576 1573 return; 1577 1574 1578 1575 out_baddir: ··· 1643 1634 if (!proc_error) { 1644 1635 /* Processing error: drop the request */ 1645 1636 xprt_free_bc_request(req); 1637 + svc_release_rqst(rqstp); 1646 1638 return; 1647 1639 } 1648 1640 /* Finally, send the reply synchronously */ ··· 1657 1647 timeout.to_maxval = timeout.to_initval; 1658 1648 memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf)); 1659 1649 task = rpc_run_bc_task(req, &timeout); 1650 + svc_release_rqst(rqstp); 1660 1651 1661 1652 if (IS_ERR(task)) 1662 1653 return;
+13
net/sunrpc/svc_xprt.c
··· 1014 1014 struct svc_serv *serv = xprt->xpt_server; 1015 1015 struct svc_deferred_req *dr; 1016 1016 1017 + /* unregister with rpcbind for when transport type is TCP or UDP. 1018 + */ 1019 + if (test_bit(XPT_RPCB_UNREG, &xprt->xpt_flags)) { 1020 + struct svc_sock *svsk = container_of(xprt, struct svc_sock, 1021 + sk_xprt); 1022 + struct socket *sock = svsk->sk_sock; 1023 + 1024 + if (svc_register(serv, xprt->xpt_net, sock->sk->sk_family, 1025 + sock->sk->sk_protocol, 0) < 0) 1026 + pr_warn("failed to unregister %s with rpcbind\n", 1027 + xprt->xpt_class->xcl_name); 1028 + } 1029 + 1017 1030 if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) 1018 1031 return; 1019 1032
+11 -14
net/sunrpc/svcsock.c
··· 836 836 /* data might have come in before data_ready set up */ 837 837 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); 838 838 set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); 839 + set_bit(XPT_RPCB_UNREG, &svsk->sk_xprt.xpt_flags); 839 840 840 841 /* make sure we get destination address info */ 841 842 switch (svsk->sk_sk->sk_family) { ··· 1225 1224 * that the pages backing @xdr are unchanging. 1226 1225 */ 1227 1226 static int svc_tcp_sendmsg(struct svc_sock *svsk, struct svc_rqst *rqstp, 1228 - rpc_fraghdr marker, int *sentp) 1227 + rpc_fraghdr marker) 1229 1228 { 1230 1229 struct msghdr msg = { 1231 1230 .msg_flags = MSG_SPLICE_PAGES, ··· 1233 1232 unsigned int count; 1234 1233 void *buf; 1235 1234 int ret; 1236 - 1237 - *sentp = 0; 1238 1235 1239 1236 /* The stream record marker is copied into a temporary page 1240 1237 * fragment buffer so that it can be included in rq_bvec. ··· 1251 1252 1 + count, sizeof(marker) + rqstp->rq_res.len); 1252 1253 ret = sock_sendmsg(svsk->sk_sock, &msg); 1253 1254 page_frag_free(buf); 1254 - if (ret < 0) 1255 - return ret; 1256 - *sentp += ret; 1257 - return 0; 1255 + return ret; 1258 1256 } 1259 1257 1260 1258 /** ··· 1270 1274 struct xdr_buf *xdr = &rqstp->rq_res; 1271 1275 rpc_fraghdr marker = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | 1272 1276 (u32)xdr->len); 1273 - int sent, err; 1277 + int sent; 1274 1278 1275 1279 svc_tcp_release_ctxt(xprt, rqstp->rq_xprt_ctxt); 1276 1280 rqstp->rq_xprt_ctxt = NULL; ··· 1278 1282 mutex_lock(&xprt->xpt_mutex); 1279 1283 if (svc_xprt_is_dead(xprt)) 1280 1284 goto out_notconn; 1281 - err = svc_tcp_sendmsg(svsk, rqstp, marker, &sent); 1282 - trace_svcsock_tcp_send(xprt, err < 0 ? (long)err : sent); 1283 - if (err < 0 || sent != (xdr->len + sizeof(marker))) 1285 + sent = svc_tcp_sendmsg(svsk, rqstp, marker); 1286 + trace_svcsock_tcp_send(xprt, sent); 1287 + if (sent < 0 || sent != (xdr->len + sizeof(marker))) 1284 1288 goto out_close; 1285 1289 mutex_unlock(&xprt->xpt_mutex); 1286 1290 return sent; ··· 1289 1293 mutex_unlock(&xprt->xpt_mutex); 1290 1294 return -ENOTCONN; 1291 1295 out_close: 1292 - pr_notice("rpc-srv/tcp: %s: %s %d when sending %d bytes - shutting down socket\n", 1296 + pr_notice("rpc-srv/tcp: %s: %s %d when sending %zu bytes - shutting down socket\n", 1293 1297 xprt->xpt_server->sv_name, 1294 - (err < 0) ? "got error" : "sent", 1295 - (err < 0) ? err : sent, xdr->len); 1298 + (sent < 0) ? "got error" : "sent", 1299 + sent, xdr->len + sizeof(marker)); 1296 1300 svc_xprt_deferred_close(xprt); 1297 1301 mutex_unlock(&xprt->xpt_mutex); 1298 1302 return -EAGAIN; ··· 1351 1355 if (sk->sk_state == TCP_LISTEN) { 1352 1356 strcpy(svsk->sk_xprt.xpt_remotebuf, "listener"); 1353 1357 set_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags); 1358 + set_bit(XPT_RPCB_UNREG, &svsk->sk_xprt.xpt_flags); 1354 1359 sk->sk_data_ready = svc_tcp_listen_data_ready; 1355 1360 set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); 1356 1361 } else {
+1 -1
net/sunrpc/sysfs.c
··· 389 389 saddr = (struct sockaddr *)&xprt->addr; 390 390 port = rpc_get_port(saddr); 391 391 392 - /* buf_len is the len until the first occurence of either 392 + /* buf_len is the len until the first occurrence of either 393 393 * '\n' or '\0' 394 394 */ 395 395 buf_len = strcspn(buf, "\n");
+1 -1
tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_opaque.j2
··· 13 13 {% if annotate %} 14 14 /* (fixed-length opaque) */ 15 15 {% endif %} 16 - return xdr_stream_decode_opaque_fixed(xdr, ptr, {{ size }}) >= 0; 16 + return xdr_stream_decode_opaque_fixed(xdr, ptr, {{ size }}) == 0; 17 17 };