Skip to content

Commit ce3f5bb

Browse files
committed
Merge tag 'nfsd-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd updates from Chuck Lever: "NFSD is finally able to offer write delegations to clients that open files with O_WRONLY, thanks to patches from Dai Ngo. We're expecting this to accelerate a few interesting corner cases. The cap on the number of operations per NFSv4 COMPOUND has been lifted. Now, clients that send COMPOUNDs containing dozens of operations (for example, a long stream of LOOKUP operations to walk a pathname in a single round trip) will no longer be rejected. This release re-enables the ability for NFSD to perform NFSv4.2 COPY operations asynchronously. This feature has been disabled to mitigate the risk of denial-of-service when too many such requests arrive. Many thanks to the contributors, reviewers, testers, and bug reporters who participated during the v6.17 development cycle" * tag 'nfsd-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (32 commits) nfsd: Drop dprintk in blocklayout xdr functions sunrpc: make svc_tcp_sendmsg() take a signed sentp pointer sunrpc: rearrange struct svc_rqst for fewer cachelines sunrpc: return better error in svcauth_gss_accept() on alloc failure sunrpc: reset rq_accept_statp when starting a new RPC sunrpc: remove SVC_SYSERR sunrpc: fix handling of unknown auth status codes NFSD: Simplify struct knfsd_fh NFSD: Access a knfsd_fh's fsid by pointer Revert "NFSD: Force all NFSv4.2 COPY requests to be synchronous" NFSD: Avoid multiple -Wflex-array-member-not-at-end warnings NFSD: Use vfs_iocb_iter_write() NFSD: Use vfs_iocb_iter_read() NFSD: Clean up kdoc for nfsd_open_local_fh() NFSD: Clean up kdoc for nfsd_file_put_local() NFSD: Remove definition for trace_nfsd_ctl_maxconn NFSD: Remove definition for trace_nfsd_file_gc_recent NFSD: Remove definitions for unused trace_nfsd_file_lru trace points NFSD: Remove definition for trace_nfsd_file_unhash_and_queue nfsd: Use correct error code when decoding extents ...
2 parents a90f1b6 + e339967 commit ce3f5bb

31 files changed

Lines changed: 341 additions & 347 deletions

fs/nfsd/blocklayout.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,13 @@ nfsd4_block_proc_layoutcommit(struct inode *inode,
178178
{
179179
struct iomap *iomaps;
180180
int nr_iomaps;
181+
__be32 nfserr;
181182

182-
nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
183-
lcp->lc_up_len, &iomaps, i_blocksize(inode));
184-
if (nr_iomaps < 0)
185-
return nfserrno(nr_iomaps);
183+
nfserr = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
184+
lcp->lc_up_len, &iomaps, &nr_iomaps,
185+
i_blocksize(inode));
186+
if (nfserr != nfs_ok)
187+
return nfserr;
186188

187189
return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps);
188190
}
@@ -316,11 +318,13 @@ nfsd4_scsi_proc_layoutcommit(struct inode *inode,
316318
{
317319
struct iomap *iomaps;
318320
int nr_iomaps;
321+
__be32 nfserr;
319322

320-
nr_iomaps = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
321-
lcp->lc_up_len, &iomaps, i_blocksize(inode));
322-
if (nr_iomaps < 0)
323-
return nfserrno(nr_iomaps);
323+
nfserr = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
324+
lcp->lc_up_len, &iomaps, &nr_iomaps,
325+
i_blocksize(inode));
326+
if (nfserr != nfs_ok)
327+
return nfserr;
324328

325329
return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps);
326330
}

fs/nfsd/blocklayoutxdr.c

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -112,35 +112,46 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
112112
return 0;
113113
}
114114

115-
int
115+
/**
116+
* nfsd4_block_decode_layoutupdate - decode the block layout extent array
117+
* @p: pointer to the xdr data
118+
* @len: number of bytes to decode
119+
* @iomapp: pointer to store the decoded extent array
120+
* @nr_iomapsp: pointer to store the number of extents
121+
* @block_size: alignment of extent offset and length
122+
*
123+
* This function decodes the opaque field of the layoutupdate4 structure
124+
* in a layoutcommit request for the block layout driver. The field is
125+
* actually an array of extents sent by the client. It also checks that
126+
* the file offset, storage offset and length of each extent are aligned
127+
* by @block_size.
128+
*
129+
* Return values:
130+
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
131+
* %nfserr_bad_xdr: The encoded array in @p is invalid
132+
* %nfserr_inval: An unaligned extent found
133+
* %nfserr_delay: Failed to allocate memory for @iomapp
134+
*/
135+
__be32
116136
nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
117-
u32 block_size)
137+
int *nr_iomapsp, u32 block_size)
118138
{
119139
struct iomap *iomaps;
120140
u32 nr_iomaps, i;
121141

122-
if (len < sizeof(u32)) {
123-
dprintk("%s: extent array too small: %u\n", __func__, len);
124-
return -EINVAL;
125-
}
142+
if (len < sizeof(u32))
143+
return nfserr_bad_xdr;
126144
len -= sizeof(u32);
127-
if (len % PNFS_BLOCK_EXTENT_SIZE) {
128-
dprintk("%s: extent array invalid: %u\n", __func__, len);
129-
return -EINVAL;
130-
}
145+
if (len % PNFS_BLOCK_EXTENT_SIZE)
146+
return nfserr_bad_xdr;
131147

132148
nr_iomaps = be32_to_cpup(p++);
133-
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) {
134-
dprintk("%s: extent array size mismatch: %u/%u\n",
135-
__func__, len, nr_iomaps);
136-
return -EINVAL;
137-
}
149+
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE)
150+
return nfserr_bad_xdr;
138151

139152
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
140-
if (!iomaps) {
141-
dprintk("%s: failed to allocate extent array\n", __func__);
142-
return -ENOMEM;
143-
}
153+
if (!iomaps)
154+
return nfserr_delay;
144155

145156
for (i = 0; i < nr_iomaps; i++) {
146157
struct pnfs_block_extent bex;
@@ -150,26 +161,18 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
150161

151162
p = xdr_decode_hyper(p, &bex.foff);
152163
if (bex.foff & (block_size - 1)) {
153-
dprintk("%s: unaligned offset 0x%llx\n",
154-
__func__, bex.foff);
155164
goto fail;
156165
}
157166
p = xdr_decode_hyper(p, &bex.len);
158167
if (bex.len & (block_size - 1)) {
159-
dprintk("%s: unaligned length 0x%llx\n",
160-
__func__, bex.foff);
161168
goto fail;
162169
}
163170
p = xdr_decode_hyper(p, &bex.soff);
164171
if (bex.soff & (block_size - 1)) {
165-
dprintk("%s: unaligned disk offset 0x%llx\n",
166-
__func__, bex.soff);
167172
goto fail;
168173
}
169174
bex.es = be32_to_cpup(p++);
170175
if (bex.es != PNFS_BLOCK_READWRITE_DATA) {
171-
dprintk("%s: incorrect extent state %d\n",
172-
__func__, bex.es);
173176
goto fail;
174177
}
175178

@@ -178,59 +181,71 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
178181
}
179182

180183
*iomapp = iomaps;
181-
return nr_iomaps;
184+
*nr_iomapsp = nr_iomaps;
185+
return nfs_ok;
182186
fail:
183187
kfree(iomaps);
184-
return -EINVAL;
188+
return nfserr_inval;
185189
}
186190

187-
int
191+
/**
192+
* nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array
193+
* @p: pointer to the xdr data
194+
* @len: number of bytes to decode
195+
* @iomapp: pointer to store the decoded extent array
196+
* @nr_iomapsp: pointer to store the number of extents
197+
* @block_size: alignment of extent offset and length
198+
*
199+
* This function decodes the opaque field of the layoutupdate4 structure
200+
* in a layoutcommit request for the scsi layout driver. The field is
201+
* actually an array of extents sent by the client. It also checks that
202+
* the offset and length of each extent are aligned by @block_size.
203+
*
204+
* Return values:
205+
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
206+
* %nfserr_bad_xdr: The encoded array in @p is invalid
207+
* %nfserr_inval: An unaligned extent found
208+
* %nfserr_delay: Failed to allocate memory for @iomapp
209+
*/
210+
__be32
188211
nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
189-
u32 block_size)
212+
int *nr_iomapsp, u32 block_size)
190213
{
191214
struct iomap *iomaps;
192215
u32 nr_iomaps, expected, i;
193216

194-
if (len < sizeof(u32)) {
195-
dprintk("%s: extent array too small: %u\n", __func__, len);
196-
return -EINVAL;
197-
}
217+
if (len < sizeof(u32))
218+
return nfserr_bad_xdr;
198219

199220
nr_iomaps = be32_to_cpup(p++);
200221
expected = sizeof(__be32) + nr_iomaps * PNFS_SCSI_RANGE_SIZE;
201-
if (len != expected) {
202-
dprintk("%s: extent array size mismatch: %u/%u\n",
203-
__func__, len, expected);
204-
return -EINVAL;
205-
}
222+
if (len != expected)
223+
return nfserr_bad_xdr;
206224

207225
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
208-
if (!iomaps) {
209-
dprintk("%s: failed to allocate extent array\n", __func__);
210-
return -ENOMEM;
211-
}
226+
if (!iomaps)
227+
return nfserr_delay;
212228

213229
for (i = 0; i < nr_iomaps; i++) {
214230
u64 val;
215231

216232
p = xdr_decode_hyper(p, &val);
217233
if (val & (block_size - 1)) {
218-
dprintk("%s: unaligned offset 0x%llx\n", __func__, val);
219234
goto fail;
220235
}
221236
iomaps[i].offset = val;
222237

223238
p = xdr_decode_hyper(p, &val);
224239
if (val & (block_size - 1)) {
225-
dprintk("%s: unaligned length 0x%llx\n", __func__, val);
226240
goto fail;
227241
}
228242
iomaps[i].length = val;
229243
}
230244

231245
*iomapp = iomaps;
232-
return nr_iomaps;
246+
*nr_iomapsp = nr_iomaps;
247+
return nfs_ok;
233248
fail:
234249
kfree(iomaps);
235-
return -EINVAL;
250+
return nfserr_inval;
236251
}

fs/nfsd/blocklayoutxdr.h

Lines changed: 4 additions & 4 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-
int nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
58-
u32 block_size);
59-
int nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
60-
u32 block_size);
57+
__be32 nfsd4_block_decode_layoutupdate(__be32 *p, u32 len,
58+
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
59+
__be32 nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len,
60+
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
6161

6262
#endif /* _NFSD_BLOCKLAYOUTXDR_H */

fs/nfsd/export.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
8282
int len;
8383
struct auth_domain *dom = NULL;
8484
int err;
85-
int fsidtype;
86-
char *ep;
85+
u8 fsidtype;
8786
struct svc_expkey key;
8887
struct svc_expkey *ek = NULL;
8988

@@ -109,10 +108,9 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
109108
err = -EINVAL;
110109
if (qword_get(&mesg, buf, PAGE_SIZE) <= 0)
111110
goto out;
112-
fsidtype = simple_strtoul(buf, &ep, 10);
113-
if (*ep)
111+
if (kstrtou8(buf, 10, &fsidtype))
114112
goto out;
115-
dprintk("found fsidtype %d\n", fsidtype);
113+
dprintk("found fsidtype %u\n", fsidtype);
116114
if (key_len(fsidtype)==0) /* invalid type */
117115
goto out;
118116
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)

fs/nfsd/export.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct svc_expkey {
8888
struct cache_head h;
8989

9090
struct auth_domain * ek_client;
91-
int ek_fsidtype;
91+
u8 ek_fsidtype;
9292
u32 ek_fsid[6];
9393

9494
struct path ek_path;

fs/nfsd/filecache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ nfsd_file_put(struct nfsd_file *nf)
372372

373373
/**
374374
* nfsd_file_put_local - put nfsd_file reference and arm nfsd_net_put in caller
375-
* @nf: nfsd_file of which to put the reference
375+
* @pnf: nfsd_file of which to put the reference
376376
*
377377
* First save the associated net to return to caller, then put
378378
* the reference of the nfsd_file.

fs/nfsd/localio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @rpc_clnt: rpc_clnt that the client established
3333
* @cred: cred that the client established
3434
* @nfs_fh: filehandle to lookup
35-
* @nfp: place to find the nfsd_file, or store it if it was non-NULL
35+
* @pnf: place to find the nfsd_file, or store it if it was non-NULL
3636
* @fmode: fmode_t to use for open
3737
*
3838
* This function maps a local fh to a path on a local filesystem.

fs/nfsd/nfs3proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
561561
buf->pages = rqstp->rq_next_page;
562562
rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
563563

564-
xdr_init_encode_pages(xdr, buf, buf->pages, NULL);
564+
xdr_init_encode_pages(xdr, buf);
565565
}
566566

567567
/*

fs/nfsd/nfs4layouts.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ nfsd4_alloc_devid_map(const struct svc_fh *fhp)
6565
return;
6666

6767
map->fsid_type = fh->fh_fsid_type;
68-
memcpy(&map->fsid, fh->fh_fsid, fsid_len);
68+
memcpy(&map->fsid, fh_fsid(fh), fsid_len);
6969

7070
spin_lock(&nfsd_devid_lock);
7171
if (fhp->fh_export->ex_devid_map)
@@ -75,7 +75,7 @@ nfsd4_alloc_devid_map(const struct svc_fh *fhp)
7575
list_for_each_entry(old, &nfsd_devid_hash[i], hash) {
7676
if (old->fsid_type != fh->fh_fsid_type)
7777
continue;
78-
if (memcmp(old->fsid, fh->fh_fsid,
78+
if (memcmp(old->fsid, fh_fsid(fh),
7979
key_len(old->fsid_type)))
8080
continue;
8181

fs/nfsd/nfs4proc.c

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,13 +1917,6 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
19171917
struct nfsd42_write_res *result;
19181918
__be32 status;
19191919

1920-
/*
1921-
* Currently, async COPY is not reliable. Force all COPY
1922-
* requests to be synchronous to avoid client application
1923-
* hangs waiting for COPY completion.
1924-
*/
1925-
nfsd4_copy_set_sync(copy, true);
1926-
19271920
result = &copy->cp_res;
19281921
nfsd_copy_write_verifier((__be32 *)&result->wr_verifier.data, nn);
19291922

@@ -2842,20 +2835,10 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
28422835

28432836
rqstp->rq_lease_breaker = (void **)&cstate->clp;
28442837

2845-
trace_nfsd_compound(rqstp, args->tag, args->taglen, args->client_opcnt);
2838+
trace_nfsd_compound(rqstp, args->tag, args->taglen, args->opcnt);
28462839
while (!status && resp->opcnt < args->opcnt) {
28472840
op = &args->ops[resp->opcnt++];
28482841

2849-
if (unlikely(resp->opcnt == NFSD_MAX_OPS_PER_COMPOUND)) {
2850-
/* If there are still more operations to process,
2851-
* stop here and report NFS4ERR_RESOURCE. */
2852-
if (cstate->minorversion == 0 &&
2853-
args->client_opcnt > resp->opcnt) {
2854-
op->status = nfserr_resource;
2855-
goto encode_op;
2856-
}
2857-
}
2858-
28592842
/*
28602843
* The XDR decode routines may have pre-set op->status;
28612844
* for example, if there is a miscellaneous XDR error
@@ -2932,7 +2915,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
29322915
status = op->status;
29332916
}
29342917

2935-
trace_nfsd_compound_status(args->client_opcnt, resp->opcnt,
2918+
trace_nfsd_compound_status(args->opcnt, resp->opcnt,
29362919
status, nfsd4_op_name(op->opnum));
29372920

29382921
nfsd4_cstate_clear_replay(cstate);

0 commit comments

Comments
 (0)