Skip to content

Commit 840ef6c

Browse files
committed
Merge tag 'nfs-for-7.2-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client updates from Anna Schumaker: "New features: - XPRTRDMA: Decouple req recycling from RPC completion - NFS: Expose FMODE_NOWAIT for read-only files Bugfixes: - SUNRPC: - Fix sunrpc sysfs error handling - Fix uninitialized xprt_create_args structure - XPRTRDMA: - Harden connect and reply handling - NFS: - Fix EOF updates after fallocate/zero-range - Keep PG_UPTODATE clear after read errors in page groups - Use nfsi->rwsem to protect traversal of the file lock list - Prevent resource leak in nfs_alloc_server() - NFSv4: - Clear exception state on successful mkdir retry - Don't skip revalidate when holding a dir delegation and attrs are stale - pNFS: - Fix use-after-free in pnfs_update_layout() - Defer return_range callbacks until after inode unlock - Fix LAYOUTCOMMIT retry loop on OLD_STATEID - Reject zero-length r_addr in nfs4_decode_mp_ds_addr - NFS/flexfiles: - Reject zero-length filehandle version arrays - Fix checking if a layout is striped - Fixes for honoring FF_FLAGS_NO_IO_THRU_MDS Other cleanups and improvements: - Remove the fileid field from struct nfs_inode - Move long-delayed xprtrdma work onto the system_dfl_long_wq - Convert xprtrdma send buffer free list to an llist - Show "<redacted>" for cert_serial and privkey_serial mount options" * tag 'nfs-for-7.2-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (42 commits) NFS: Use common error handling code in nfs_alloc_server() NFS: Prevent resource leak in nfs_alloc_server() NFSv4/pNFS: reject zero-length r_addr in nfs4_decode_mp_ds_addr nfs: don't skip revalidate on directory delegation when attrs flagged stale xprtrdma: Return sendctx slot after Send preparation failure xprtrdma: Repost Receive buffers for malformed replies xprtrdma: Sanitize the reply credit grant after parsing xprtrdma: Fix bcall rep leak and unbounded peek xprtrdma: Resize reply buffers before reposting receives xprtrdma: Check frwr_wp_create() during connect xprtrdma: Initialize re_id before removal registration xprtrdma: Fix ep kref imbalance on ADDR_CHANGE xprtrdma: Convert send buffer free list to llist NFS: correct CONFIG_NFS_V4 macro name in #endif comment nfs: use nfsi->rwsem to protect traversal of the file lock list NFSv4.1/pNFS: fix LAYOUTCOMMIT retry loop on OLD_STATEID nfs: expose FMODE_NOWAIT for read-only files nfs: add nowait version of nfs_start_io_direct NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS in pg_get_mirror_count_write NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS on fatal DS connect errors ...
2 parents 09ca8dc + 284ea3f commit 840ef6c

35 files changed

Lines changed: 703 additions & 326 deletions

‎Documentation/admin-guide/kernel-parameters.txt‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4288,13 +4288,6 @@ Kernel parameters
42884288
Only applies if the softerr mount option is enabled,
42894289
and the specified value is >= 0.
42904290

4291-
nfs.enable_ino64=
4292-
[NFS] enable 64-bit inode numbers.
4293-
If zero, the NFS client will fake up a 32-bit inode
4294-
number for the readdir() and stat() syscalls instead
4295-
of returning the full 64-bit number.
4296-
The default is to return 64-bit inode numbers.
4297-
42984291
nfs.idmap_cache_timeout=
42994292
[NFS] set the maximum lifetime for idmapper cache
43004293
entries.

‎fs/nfs/callback_proc.c‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
257257
struct pnfs_layout_hdr *lo;
258258
u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
259259
LIST_HEAD(free_me_list);
260+
bool return_range = false;
260261

261262
ino = nfs_layout_find_inode(clp, &args->cbl_fh, &args->cbl_stateid);
262263
if (IS_ERR(ino)) {
@@ -301,13 +302,13 @@ static u32 initiate_file_draining(struct nfs_client *clp,
301302
/* Embrace your forgetfulness! */
302303
rv = NFS4ERR_NOMATCHING_LAYOUT;
303304

304-
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
305-
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
306-
&args->cbl_range);
307-
}
305+
return_range = true;
308306
}
309307
unlock:
310308
spin_unlock(&ino->i_lock);
309+
if (return_range && NFS_SERVER(ino)->pnfs_curr_ld->return_range)
310+
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
311+
&args->cbl_range);
311312
pnfs_free_lseg_list(&free_me_list);
312313
/* Free all lsegs that are attached to commit buckets */
313314
nfs_commit_inode(ino, 0);

‎fs/nfs/client.c‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,10 +1063,8 @@ struct nfs_server *nfs_alloc_server(void)
10631063
return NULL;
10641064

10651065
server->s_sysfs_id = ida_alloc(&s_sysfs_ids, GFP_KERNEL);
1066-
if (server->s_sysfs_id < 0) {
1067-
kfree(server);
1068-
return NULL;
1069-
}
1066+
if (server->s_sysfs_id < 0)
1067+
goto free_server;
10701068

10711069
server->client = server->client_acl = ERR_PTR(-EINVAL);
10721070

@@ -1088,8 +1086,8 @@ struct nfs_server *nfs_alloc_server(void)
10881086

10891087
server->io_stats = nfs_alloc_iostats();
10901088
if (!server->io_stats) {
1091-
kfree(server);
1092-
return NULL;
1089+
ida_free(&s_sysfs_ids, server->s_sysfs_id);
1090+
goto free_server;
10931091
}
10941092

10951093
server->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
@@ -1103,6 +1101,10 @@ struct nfs_server *nfs_alloc_server(void)
11031101
rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC");
11041102

11051103
return server;
1104+
1105+
free_server:
1106+
kfree(server);
1107+
return NULL;
11061108
}
11071109
EXPORT_SYMBOL_GPL(nfs_alloc_server);
11081110

‎fs/nfs/delegation.c‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ int nfs4_check_delegation(struct inode *inode, fmode_t type)
173173
static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_stateid *stateid)
174174
{
175175
struct inode *inode = state->inode;
176+
struct nfs_inode *nfsi = NFS_I(inode);
176177
struct file_lock *fl;
177178
struct file_lock_context *flctx = locks_inode_context(inode);
178179
struct list_head *list;
@@ -182,22 +183,28 @@ static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_state
182183
goto out;
183184

184185
list = &flctx->flc_posix;
186+
187+
/* Guard against reclaim and new lock/unlock calls */
188+
down_write(&nfsi->rwsem);
185189
spin_lock(&flctx->flc_lock);
186190
restart:
187191
for_each_file_lock(fl, list) {
188192
if (nfs_file_open_context(fl->c.flc_file)->state != state)
189193
continue;
190194
spin_unlock(&flctx->flc_lock);
191195
status = nfs4_lock_delegation_recall(fl, state, stateid);
192-
if (status < 0)
196+
if (status < 0) {
197+
up_write(&nfsi->rwsem);
193198
goto out;
199+
}
194200
spin_lock(&flctx->flc_lock);
195201
}
196202
if (list == &flctx->flc_posix) {
197203
list = &flctx->flc_flock;
198204
goto restart;
199205
}
200206
spin_unlock(&flctx->flc_lock);
207+
up_write(&nfsi->rwsem);
201208
out:
202209
return status;
203210
}

‎fs/nfs/dir.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
650650
return 0;
651651

652652
nfsi = NFS_I(inode);
653-
if (entry->fattr->fileid != nfsi->fileid)
653+
if (entry->fattr->fileid != inode->i_ino)
654654
return 0;
655655
if (entry->fh->size && nfs_compare_fh(entry->fh, &nfsi->fh) != 0)
656656
return 0;
@@ -1105,7 +1105,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
11051105

11061106
ent = &array->array[i];
11071107
if (!dir_emit(desc->ctx, ent->name, ent->name_len,
1108-
nfs_compat_user_ino64(ent->ino), ent->d_type)) {
1108+
ent->ino, ent->d_type)) {
11091109
desc->eob = true;
11101110
break;
11111111
}
@@ -2301,7 +2301,7 @@ nfs4_lookup_revalidate(struct inode *dir, const struct qstr *name,
23012301
return nfs_do_lookup_revalidate(dir, name, dentry, flags);
23022302
}
23032303

2304-
#endif /* CONFIG_NFSV4 */
2304+
#endif /* CONFIG_NFS_V4 */
23052305

23062306
int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry,
23072307
struct file *file, unsigned int open_flags,

‎fs/nfs/direct.c‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,14 +466,22 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
466466
goto out_release;
467467
}
468468
dreq->l_ctx = l_ctx;
469-
if (!is_sync_kiocb(iocb))
469+
if (!is_sync_kiocb(iocb)) {
470470
dreq->iocb = iocb;
471+
} else if (iocb->ki_flags & IOCB_NOWAIT) {
472+
result = -EAGAIN;
473+
nfs_direct_req_release(dreq);
474+
goto out_release;
475+
}
471476

472477
if (user_backed_iter(iter))
473478
dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
474479

475480
if (!swap) {
476-
result = nfs_start_io_direct(inode);
481+
if (iocb->ki_flags & IOCB_NOWAIT)
482+
result = nfs_start_io_direct_nowait(inode);
483+
else
484+
result = nfs_start_io_direct(inode);
477485
if (result) {
478486
/* release the reference that would usually be
479487
* consumed by nfs_direct_read_schedule_iovec()

‎fs/nfs/export.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent)
4949
return FILEID_INVALID;
5050
}
5151

52-
p[FILEID_HIGH_OFF] = NFS_FILEID(inode) >> 32;
53-
p[FILEID_LOW_OFF] = NFS_FILEID(inode);
52+
p[FILEID_HIGH_OFF] = inode->i_ino >> 32;
53+
p[FILEID_LOW_OFF] = inode->i_ino;
5454
p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT;
5555
p[len - 1] = 0; /* Padding */
5656
nfs_copy_fh(clnt_fh, server_fh);
5757
*max_len = len;
5858
dprintk("%s: result fh fileid %llu mode %u size %d\n",
59-
__func__, NFS_FILEID(inode), inode->i_mode, *max_len);
59+
__func__, inode->i_ino, inode->i_mode, *max_len);
6060
return *max_len;
6161
}
6262

‎fs/nfs/file.c‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,12 @@ nfs_file_open(struct inode *inode, struct file *filp)
7272
return res;
7373

7474
res = nfs_open(inode, filp);
75-
if (res == 0)
75+
if (res == 0) {
7676
filp->f_mode |= FMODE_CAN_ODIRECT;
77+
/* flag NOWAIT on read-only files only */
78+
if (!(filp->f_mode & FMODE_WRITE))
79+
filp->f_mode |= FMODE_NOWAIT;
80+
}
7781
return res;
7882
}
7983

@@ -166,6 +170,10 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
166170
if (iocb->ki_flags & IOCB_DIRECT)
167171
return nfs_file_direct_read(iocb, to, false);
168172

173+
/* NOWAIT only supported on direct reads */
174+
if (iocb->ki_flags & IOCB_NOWAIT)
175+
return -EAGAIN;
176+
169177
dprintk("NFS: read(%pD2, %zu@%lu)\n",
170178
iocb->ki_filp,
171179
iov_iter_count(to), (unsigned long) iocb->ki_pos);
@@ -705,6 +713,12 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
705713

706714
trace_nfs_file_write(iocb, from);
707715

716+
/*
717+
* FMODE_NOWAIT is not set for writable files
718+
*/
719+
if (WARN_ON_ONCE(iocb->ki_flags & IOCB_NOWAIT))
720+
return -EAGAIN;
721+
708722
result = nfs_key_timeout_notify(file, inode);
709723
if (result)
710724
return result;

‎fs/nfs/filelayout/filelayout.c‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static void filelayout_reset_write(struct nfs_pgio_header *hdr)
9595
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
9696
hdr->task.tk_pid,
9797
hdr->inode->i_sb->s_id,
98-
(unsigned long long)NFS_FILEID(hdr->inode),
98+
(unsigned long long)hdr->inode->i_ino,
9999
hdr->args.count,
100100
(unsigned long long)hdr->args.offset);
101101

@@ -112,7 +112,7 @@ static void filelayout_reset_read(struct nfs_pgio_header *hdr)
112112
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
113113
hdr->task.tk_pid,
114114
hdr->inode->i_sb->s_id,
115-
(unsigned long long)NFS_FILEID(hdr->inode),
115+
(unsigned long long)hdr->inode->i_ino,
116116
hdr->args.count,
117117
(unsigned long long)hdr->args.offset);
118118

@@ -778,6 +778,8 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
778778
static bool
779779
filelayout_lseg_is_striped(const struct nfs4_filelayout_segment *flseg)
780780
{
781+
if (flseg->dsaddr)
782+
return flseg->dsaddr->stripe_count > 1;
781783
return flseg->num_fh > 1;
782784
}
783785

‎fs/nfs/flexfilelayout/flexfilelayout.c‎

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
551551
if (!p)
552552
goto out_err_free;
553553
fh_count = be32_to_cpup(p);
554+
if (fh_count == 0) {
555+
rc = -EINVAL;
556+
goto out_err_free;
557+
}
554558

555559
dss_info->fh_versions =
556560
kzalloc_objs(struct nfs_fh, fh_count, gfp_flags);
@@ -632,6 +636,9 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
632636
if (!p)
633637
goto out_sort_mirrors;
634638
fls->flags = be32_to_cpup(p);
639+
if (fls->flags & FF_FLAGS_NO_IO_THRU_MDS)
640+
set_bit(NFS4_FF_HDR_NO_IO_THRU_MDS,
641+
&FF_LAYOUT_FROM_HDR(lh)->flags);
635642

636643
p = xdr_inline_decode(&stream, 4);
637644
if (!p)
@@ -1181,6 +1188,16 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
11811188
0, NFS4_MAX_UINT64, IOMODE_RW,
11821189
NFS_I(pgio->pg_inode)->layout,
11831190
pgio->pg_lseg);
1191+
if (NFS_I(pgio->pg_inode)->layout &&
1192+
ff_layout_hdr_no_fallback_to_mds(NFS_I(pgio->pg_inode)->layout)) {
1193+
/*
1194+
* FF_FLAGS_NO_IO_THRU_MDS: no current lseg but the server's
1195+
* policy forbids MDS fallback. Surface -EAGAIN so writeback
1196+
* retries rather than silently issuing the WRITE via MDS.
1197+
*/
1198+
pgio->pg_error = -EAGAIN;
1199+
goto out;
1200+
}
11841201
/* no lseg means that pnfs is not in use, so no mirroring here */
11851202
nfs_pageio_reset_write_mds(pgio);
11861203
out:
@@ -1230,7 +1247,7 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
12301247
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
12311248
hdr->task.tk_pid,
12321249
hdr->inode->i_sb->s_id,
1233-
(unsigned long long)NFS_FILEID(hdr->inode),
1250+
(unsigned long long)hdr->inode->i_ino,
12341251
hdr->args.count,
12351252
(unsigned long long)hdr->args.offset);
12361253

@@ -1243,7 +1260,7 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
12431260
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
12441261
hdr->task.tk_pid,
12451262
hdr->inode->i_sb->s_id,
1246-
(unsigned long long)NFS_FILEID(hdr->inode),
1263+
(unsigned long long)hdr->inode->i_ino,
12471264
hdr->args.count,
12481265
(unsigned long long)hdr->args.offset);
12491266

@@ -1283,7 +1300,7 @@ static void ff_layout_reset_read(struct nfs_pgio_header *hdr)
12831300
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
12841301
hdr->task.tk_pid,
12851302
hdr->inode->i_sb->s_id,
1286-
(unsigned long long)NFS_FILEID(hdr->inode),
1303+
(unsigned long long)hdr->inode->i_ino,
12871304
hdr->args.count,
12881305
(unsigned long long)hdr->args.offset);
12891306

@@ -2200,6 +2217,14 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
22002217
out_failed:
22012218
if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error)
22022219
return PNFS_TRY_AGAIN;
2220+
if (ff_layout_no_fallback_to_mds(lseg)) {
2221+
/*
2222+
* FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET,
2223+
* never fall through to MDS I/O.
2224+
*/
2225+
pnfs_error_mark_layout_for_return(hdr->inode, lseg);
2226+
return PNFS_TRY_AGAIN;
2227+
}
22032228
trace_pnfs_mds_fallback_read_pagelist(hdr->inode,
22042229
hdr->args.offset, hdr->args.count,
22052230
IOMODE_READ, NFS_I(hdr->inode)->layout, lseg);
@@ -2285,6 +2310,14 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
22852310
out_failed:
22862311
if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error)
22872312
return PNFS_TRY_AGAIN;
2313+
if (ff_layout_no_fallback_to_mds(lseg)) {
2314+
/*
2315+
* FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET,
2316+
* never fall through to MDS I/O.
2317+
*/
2318+
pnfs_error_mark_layout_for_return(hdr->inode, lseg);
2319+
return PNFS_TRY_AGAIN;
2320+
}
22882321
trace_pnfs_mds_fallback_write_pagelist(hdr->inode,
22892322
hdr->args.offset, hdr->args.count,
22902323
IOMODE_RW, NFS_I(hdr->inode)->layout, lseg);

0 commit comments

Comments
 (0)