Skip to content

Commit 81538c8

Browse files
committed
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() ...
2 parents 256e341 + 73cc6ec commit 81538c8

40 files changed

+664
-324
lines changed

fs/attr.c

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -286,20 +286,12 @@ static void setattr_copy_mgtime(struct inode *inode, const struct iattr *attr)
286286
unsigned int ia_valid = attr->ia_valid;
287287
struct timespec64 now;
288288

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
301294
now = current_time(inode);
302-
}
303295

304296
if (ia_valid & ATTR_ATIME_SET)
305297
inode_set_atime_to_ts(inode, attr->ia_atime);
@@ -359,12 +351,11 @@ void setattr_copy(struct mnt_idmap *idmap, struct inode *inode,
359351
inode_set_atime_to_ts(inode, attr->ia_atime);
360352
if (ia_valid & ATTR_MTIME)
361353
inode_set_mtime_to_ts(inode, attr->ia_mtime);
362-
if (ia_valid & ATTR_CTIME) {
363-
if (ia_valid & ATTR_DELEG)
364-
inode_set_ctime_deleg(inode, attr->ia_ctime);
365-
else
366-
inode_set_ctime_to_ts(inode, attr->ia_ctime);
367-
}
354+
355+
if (ia_valid & ATTR_CTIME_SET)
356+
inode_set_ctime_deleg(inode, attr->ia_ctime);
357+
else if (ia_valid & ATTR_CTIME)
358+
inode_set_ctime_to_ts(inode, attr->ia_ctime);
368359
}
369360
EXPORT_SYMBOL(setattr_copy);
370361

@@ -463,15 +454,18 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
463454

464455
now = current_time(inode);
465456

466-
attr->ia_ctime = now;
467-
if (!(ia_valid & ATTR_ATIME_SET))
468-
attr->ia_atime = now;
469-
else
457+
if (ia_valid & ATTR_ATIME_SET)
470458
attr->ia_atime = timestamp_truncate(attr->ia_atime, inode);
471-
if (!(ia_valid & ATTR_MTIME_SET))
472-
attr->ia_mtime = now;
473459
else
460+
attr->ia_atime = now;
461+
if (ia_valid & ATTR_CTIME_SET)
462+
attr->ia_ctime = timestamp_truncate(attr->ia_ctime, inode);
463+
else
464+
attr->ia_ctime = now;
465+
if (ia_valid & ATTR_MTIME_SET)
474466
attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode);
467+
else
468+
attr->ia_mtime = now;
475469

476470
if (ia_valid & ATTR_KILL_PRIV) {
477471
error = security_inode_need_killpriv(dentry);

fs/lockd/svclock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
980980
struct file_lock *fl;
981981
int error;
982982

983-
dprintk("grant_reply: looking for cookie %x, s=%d \n",
983+
dprintk("grant_reply: looking for cookie %x, s=%d\n",
984984
*(unsigned int *)(cookie->data), status);
985985
if (!(block = nlmsvc_find_block(cookie)))
986986
return;

fs/nfsd/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ config NFSD
55
depends on FILE_LOCKING
66
depends on FSNOTIFY
77
select CRC32
8+
select CRYPTO_LIB_SHA256 if NFSD_V4
89
select LOCKD
910
select SUNRPC
1011
select EXPORTFS
@@ -77,7 +78,6 @@ config NFSD_V4
7778
select FS_POSIX_ACL
7879
select RPCSEC_GSS_KRB5
7980
select CRYPTO
80-
select CRYPTO_LIB_SHA256
8181
select CRYPTO_MD5
8282
select GRACE_PERIOD
8383
select NFS_V4_2_SSC_HELPER if NFS_V4_2

fs/nfsd/blocklayout.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919

2020
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)
2323
{
2424
struct nfsd4_layout_seg *seg = &args->lg_seg;
2525
struct super_block *sb = inode->i_sb;
@@ -29,6 +29,9 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
2929
u32 device_generation = 0;
3030
int error;
3131

32+
if (locks_in_grace(SVC_NET(rqstp)))
33+
return nfserr_grace;
34+
3235
if (seg->offset & (block_size - 1)) {
3336
dprintk("pnfsd: I/O misaligned\n");
3437
goto out_layoutunavailable;
@@ -118,7 +121,6 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
118121
struct iomap *iomaps, int nr_iomaps)
119122
{
120123
struct timespec64 mtime = inode_get_mtime(inode);
121-
loff_t new_size = lcp->lc_last_wr + 1;
122124
struct iattr iattr = { .ia_valid = 0 };
123125
int error;
124126

@@ -128,9 +130,9 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
128130
iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME;
129131
iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime;
130132

131-
if (new_size > i_size_read(inode)) {
133+
if (lcp->lc_size_chg) {
132134
iattr.ia_valid |= ATTR_SIZE;
133-
iattr.ia_size = new_size;
135+
iattr.ia_size = lcp->lc_newsize;
134136
}
135137

136138
error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps,
@@ -173,16 +175,18 @@ nfsd4_block_proc_getdeviceinfo(struct super_block *sb,
173175
}
174176

175177
static __be32
176-
nfsd4_block_proc_layoutcommit(struct inode *inode,
178+
nfsd4_block_proc_layoutcommit(struct inode *inode, struct svc_rqst *rqstp,
177179
struct nfsd4_layoutcommit *lcp)
178180
{
179181
struct iomap *iomaps;
180182
int nr_iomaps;
181183
__be32 nfserr;
182184

183-
nfserr = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
184-
lcp->lc_up_len, &iomaps, &nr_iomaps,
185-
i_blocksize(inode));
185+
rqstp->rq_arg = lcp->lc_up_layout;
186+
svcxdr_init_decode(rqstp);
187+
188+
nfserr = nfsd4_block_decode_layoutupdate(&rqstp->rq_arg_stream,
189+
&iomaps, &nr_iomaps, i_blocksize(inode));
186190
if (nfserr != nfs_ok)
187191
return nfserr;
188192

@@ -313,16 +317,18 @@ nfsd4_scsi_proc_getdeviceinfo(struct super_block *sb,
313317
return nfserrno(nfsd4_block_get_device_info_scsi(sb, clp, gdp));
314318
}
315319
static __be32
316-
nfsd4_scsi_proc_layoutcommit(struct inode *inode,
320+
nfsd4_scsi_proc_layoutcommit(struct inode *inode, struct svc_rqst *rqstp,
317321
struct nfsd4_layoutcommit *lcp)
318322
{
319323
struct iomap *iomaps;
320324
int nr_iomaps;
321325
__be32 nfserr;
322326

323-
nfserr = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
324-
lcp->lc_up_len, &iomaps, &nr_iomaps,
325-
i_blocksize(inode));
327+
rqstp->rq_arg = lcp->lc_up_layout;
328+
svcxdr_init_decode(rqstp);
329+
330+
nfserr = nfsd4_scsi_decode_layoutupdate(&rqstp->rq_arg_stream,
331+
&iomaps, &nr_iomaps, i_blocksize(inode));
326332
if (nfserr != nfs_ok)
327333
return nfserr;
328334

fs/nfsd/blocklayoutxdr.c

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ nfsd4_block_encode_layoutget(struct xdr_stream *xdr,
2929
*p++ = cpu_to_be32(len);
3030
*p++ = cpu_to_be32(1); /* we always return a single extent */
3131

32-
p = xdr_encode_opaque_fixed(p, &b->vol_id,
33-
sizeof(struct nfsd4_deviceid));
32+
p = svcxdr_encode_deviceid4(p, &b->vol_id);
3433
p = xdr_encode_hyper(p, b->foff);
3534
p = xdr_encode_hyper(p, b->len);
3635
p = xdr_encode_hyper(p, b->soff);
@@ -114,8 +113,7 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
114113

115114
/**
116115
* nfsd4_block_decode_layoutupdate - decode the block layout extent array
117-
* @p: pointer to the xdr data
118-
* @len: number of bytes to decode
116+
* @xdr: subbuf set to the encoded array
119117
* @iomapp: pointer to store the decoded extent array
120118
* @nr_iomapsp: pointer to store the number of extents
121119
* @block_size: alignment of extent offset and length
@@ -128,25 +126,24 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
128126
*
129127
* Return values:
130128
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
131-
* %nfserr_bad_xdr: The encoded array in @p is invalid
129+
* %nfserr_bad_xdr: The encoded array in @xdr is invalid
132130
* %nfserr_inval: An unaligned extent found
133131
* %nfserr_delay: Failed to allocate memory for @iomapp
134132
*/
135133
__be32
136-
nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
134+
nfsd4_block_decode_layoutupdate(struct xdr_stream *xdr, struct iomap **iomapp,
137135
int *nr_iomapsp, u32 block_size)
138136
{
139137
struct iomap *iomaps;
140-
u32 nr_iomaps, i;
138+
u32 nr_iomaps, expected, len, i;
139+
__be32 nfserr;
141140

142-
if (len < sizeof(u32))
143-
return nfserr_bad_xdr;
144-
len -= sizeof(u32);
145-
if (len % PNFS_BLOCK_EXTENT_SIZE)
141+
if (xdr_stream_decode_u32(xdr, &nr_iomaps))
146142
return nfserr_bad_xdr;
147143

148-
nr_iomaps = be32_to_cpup(p++);
149-
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE)
144+
len = sizeof(__be32) + xdr_stream_remaining(xdr);
145+
expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE;
146+
if (len != expected)
150147
return nfserr_bad_xdr;
151148

152149
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
@@ -156,23 +153,44 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
156153
for (i = 0; i < nr_iomaps; i++) {
157154
struct pnfs_block_extent bex;
158155

159-
memcpy(&bex.vol_id, p, sizeof(struct nfsd4_deviceid));
160-
p += XDR_QUADLEN(sizeof(struct nfsd4_deviceid));
156+
if (nfsd4_decode_deviceid4(xdr, &bex.vol_id)) {
157+
nfserr = nfserr_bad_xdr;
158+
goto fail;
159+
}
161160

162-
p = xdr_decode_hyper(p, &bex.foff);
161+
if (xdr_stream_decode_u64(xdr, &bex.foff)) {
162+
nfserr = nfserr_bad_xdr;
163+
goto fail;
164+
}
163165
if (bex.foff & (block_size - 1)) {
166+
nfserr = nfserr_inval;
167+
goto fail;
168+
}
169+
170+
if (xdr_stream_decode_u64(xdr, &bex.len)) {
171+
nfserr = nfserr_bad_xdr;
164172
goto fail;
165173
}
166-
p = xdr_decode_hyper(p, &bex.len);
167174
if (bex.len & (block_size - 1)) {
175+
nfserr = nfserr_inval;
176+
goto fail;
177+
}
178+
179+
if (xdr_stream_decode_u64(xdr, &bex.soff)) {
180+
nfserr = nfserr_bad_xdr;
168181
goto fail;
169182
}
170-
p = xdr_decode_hyper(p, &bex.soff);
171183
if (bex.soff & (block_size - 1)) {
184+
nfserr = nfserr_inval;
185+
goto fail;
186+
}
187+
188+
if (xdr_stream_decode_u32(xdr, &bex.es)) {
189+
nfserr = nfserr_bad_xdr;
172190
goto fail;
173191
}
174-
bex.es = be32_to_cpup(p++);
175192
if (bex.es != PNFS_BLOCK_READWRITE_DATA) {
193+
nfserr = nfserr_inval;
176194
goto fail;
177195
}
178196

@@ -185,13 +203,12 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
185203
return nfs_ok;
186204
fail:
187205
kfree(iomaps);
188-
return nfserr_inval;
206+
return nfserr;
189207
}
190208

191209
/**
192210
* nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array
193-
* @p: pointer to the xdr data
194-
* @len: number of bytes to decode
211+
* @xdr: subbuf set to the encoded array
195212
* @iomapp: pointer to store the decoded extent array
196213
* @nr_iomapsp: pointer to store the number of extents
197214
* @block_size: alignment of extent offset and length
@@ -203,21 +220,22 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
203220
*
204221
* Return values:
205222
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
206-
* %nfserr_bad_xdr: The encoded array in @p is invalid
223+
* %nfserr_bad_xdr: The encoded array in @xdr is invalid
207224
* %nfserr_inval: An unaligned extent found
208225
* %nfserr_delay: Failed to allocate memory for @iomapp
209226
*/
210227
__be32
211-
nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
228+
nfsd4_scsi_decode_layoutupdate(struct xdr_stream *xdr, struct iomap **iomapp,
212229
int *nr_iomapsp, u32 block_size)
213230
{
214231
struct iomap *iomaps;
215-
u32 nr_iomaps, expected, i;
232+
u32 nr_iomaps, expected, len, i;
233+
__be32 nfserr;
216234

217-
if (len < sizeof(u32))
235+
if (xdr_stream_decode_u32(xdr, &nr_iomaps))
218236
return nfserr_bad_xdr;
219237

220-
nr_iomaps = be32_to_cpup(p++);
238+
len = sizeof(__be32) + xdr_stream_remaining(xdr);
221239
expected = sizeof(__be32) + nr_iomaps * PNFS_SCSI_RANGE_SIZE;
222240
if (len != expected)
223241
return nfserr_bad_xdr;
@@ -229,14 +247,22 @@ nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
229247
for (i = 0; i < nr_iomaps; i++) {
230248
u64 val;
231249

232-
p = xdr_decode_hyper(p, &val);
250+
if (xdr_stream_decode_u64(xdr, &val)) {
251+
nfserr = nfserr_bad_xdr;
252+
goto fail;
253+
}
233254
if (val & (block_size - 1)) {
255+
nfserr = nfserr_inval;
234256
goto fail;
235257
}
236258
iomaps[i].offset = val;
237259

238-
p = xdr_decode_hyper(p, &val);
260+
if (xdr_stream_decode_u64(xdr, &val)) {
261+
nfserr = nfserr_bad_xdr;
262+
goto fail;
263+
}
239264
if (val & (block_size - 1)) {
265+
nfserr = nfserr_inval;
240266
goto fail;
241267
}
242268
iomaps[i].length = val;
@@ -247,5 +273,5 @@ nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
247273
return nfs_ok;
248274
fail:
249275
kfree(iomaps);
250-
return nfserr_inval;
276+
return nfserr;
251277
}

fs/nfsd/blocklayoutxdr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ __be32 nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
5454
const struct nfsd4_getdeviceinfo *gdp);
5555
__be32 nfsd4_block_encode_layoutget(struct xdr_stream *xdr,
5656
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,
5858
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,
6060
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
6161

6262
#endif /* _NFSD_BLOCKLAYOUTXDR_H */

0 commit comments

Comments
 (0)