Skip to content

Commit 94d471a

Browse files
committed
Merge tag 'nfs-for-6.15-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Bugfixes: - Three fixes for looping in the NFSv4 state manager delegation code - Fix for the NFSv4 state XDR code (Neil Brown) - Fix a leaked reference in nfs_lock_and_join_requests() - Fix a use-after-free in the delegation return code Features: - Implement the NFSv4.2 copy offload OFFLOAD_STATUS operation to allow monitoring of an in-progress copy - Add a mount option to force NFSv3/NFSv4 to use READDIRPLUS in a getdents() call - SUNRPC now allows some basic management of an existing RPC client's connections using sysfs - Improvements to the automated teardown of a NFS client when the container it was initiated from gets killed - Improvements to prevent tasks from getting stuck in a killable wait state after calling exit_signals()" * tag 'nfs-for-6.15-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (29 commits) nfs: Add missing release on error in nfs_lock_and_join_requests() NFSv4: Check for delegation validity in nfs_start_delegation_return_locked() NFS: Don't allow waiting for exiting tasks SUNRPC: Don't allow waiting for exiting tasks NFSv4: Treat ENETUNREACH errors as fatal for state recovery NFSv4: clp->cl_cons_state < 0 signifies an invalid nfs_client NFSv4: Further cleanups to shutdown loops NFS: Shut down the nfs_client only after all the superblocks SUNRPC: rpc_clnt_set_transport() must not change the autobind setting SUNRPC: rpcbind should never reset the port to the value '0' pNFS/flexfiles: Report ENETDOWN as a connection error pNFS/flexfiles: Treat ENETUNREACH errors as fatal in containers NFS: Treat ENETUNREACH errors as fatal in containers NFS: Add a mount option to make ENETUNREACH errors fatal sunrpc: Add a sysfs file for one-step xprt deletion sunrpc: Add a sysfs file for adding a new xprt sunrpc: Add a sysfs files for rpc_clnt information sunrpc: Add a sysfs attr for xprtsec NFS: Add implid to sysfs NFS: Extend rdirplus mount option with "force|none" ...
2 parents 5e17b5c + 8e5419d commit 94d471a

31 files changed

+807
-74
lines changed

fs/nfs/client.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,8 @@ int nfs_create_rpc_client(struct nfs_client *clp,
546546
args.flags |= RPC_CLNT_CREATE_NOPING;
547547
if (test_bit(NFS_CS_REUSEPORT, &clp->cl_flags))
548548
args.flags |= RPC_CLNT_CREATE_REUSEPORT;
549+
if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags))
550+
args.flags |= RPC_CLNT_CREATE_NETUNREACH_FATAL;
549551

550552
if (!IS_ERR(clp->cl_rpcclient))
551553
return 0;
@@ -709,6 +711,9 @@ static int nfs_init_server(struct nfs_server *server,
709711
if (ctx->flags & NFS_MOUNT_NORESVPORT)
710712
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
711713

714+
if (ctx->flags & NFS_MOUNT_NETUNREACH_FATAL)
715+
__set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags);
716+
712717
/* Allocate or find a client reference we can use */
713718
clp = nfs_get_client(&cl_init);
714719
if (IS_ERR(clp))

fs/nfs/delegation.c

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
7979
struct nfs_delegation *delegation)
8080
{
8181
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
82+
set_bit(NFS4SERV_DELEGRETURN, &server->delegation_flags);
8283
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
8384
}
8485

@@ -306,7 +307,8 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
306307
if (delegation == NULL)
307308
goto out;
308309
spin_lock(&delegation->lock);
309-
if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
310+
if (delegation->inode &&
311+
!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
310312
clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
311313
/* Refcount matched in nfs_end_delegation_return() */
312314
ret = nfs_get_delegation(delegation);
@@ -330,14 +332,16 @@ nfs_start_delegation_return(struct nfs_inode *nfsi)
330332
}
331333

332334
static void nfs_abort_delegation_return(struct nfs_delegation *delegation,
333-
struct nfs_client *clp, int err)
335+
struct nfs_server *server, int err)
334336
{
335-
336337
spin_lock(&delegation->lock);
337338
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
338339
if (err == -EAGAIN) {
339340
set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
340-
set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state);
341+
set_bit(NFS4SERV_DELEGRETURN_DELAYED,
342+
&server->delegation_flags);
343+
set_bit(NFS4CLNT_DELEGRETURN_DELAYED,
344+
&server->nfs_client->cl_state);
341345
}
342346
spin_unlock(&delegation->lock);
343347
}
@@ -547,7 +551,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
547551
*/
548552
static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync)
549553
{
550-
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
554+
struct nfs_server *server = NFS_SERVER(inode);
551555
unsigned int mode = O_WRONLY | O_RDWR;
552556
int err = 0;
553557

@@ -569,11 +573,11 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
569573
/*
570574
* Guard against state recovery
571575
*/
572-
err = nfs4_wait_clnt_recover(clp);
576+
err = nfs4_wait_clnt_recover(server->nfs_client);
573577
}
574578

575579
if (err) {
576-
nfs_abort_delegation_return(delegation, clp, err);
580+
nfs_abort_delegation_return(delegation, server, err);
577581
goto out;
578582
}
579583

@@ -590,17 +594,6 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
590594

591595
if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
592596
ret = true;
593-
else if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) {
594-
struct inode *inode;
595-
596-
spin_lock(&delegation->lock);
597-
inode = delegation->inode;
598-
if (inode && list_empty(&NFS_I(inode)->open_files))
599-
ret = true;
600-
spin_unlock(&delegation->lock);
601-
}
602-
if (ret)
603-
clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
604597
if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) ||
605598
test_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags) ||
606599
test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
@@ -619,6 +612,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
619612
struct nfs_delegation *place_holder_deleg = NULL;
620613
int err = 0;
621614

615+
if (!test_and_clear_bit(NFS4SERV_DELEGRETURN,
616+
&server->delegation_flags))
617+
return 0;
622618
restart:
623619
/*
624620
* To avoid quadratic looping we hold a reference
@@ -670,6 +666,7 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
670666
cond_resched();
671667
if (!err)
672668
goto restart;
669+
set_bit(NFS4SERV_DELEGRETURN, &server->delegation_flags);
673670
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
674671
goto out;
675672
}
@@ -684,13 +681,17 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server)
684681
struct nfs_delegation *d;
685682
bool ret = false;
686683

684+
if (!test_and_clear_bit(NFS4SERV_DELEGRETURN_DELAYED,
685+
&server->delegation_flags))
686+
goto out;
687687
list_for_each_entry_rcu (d, &server->delegations, super_list) {
688688
if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags))
689689
continue;
690690
nfs_mark_return_delegation(server, d);
691691
clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags);
692692
ret = true;
693693
}
694+
out:
694695
return ret;
695696
}
696697

@@ -878,11 +879,25 @@ int nfs4_inode_make_writeable(struct inode *inode)
878879
return nfs4_inode_return_delegation(inode);
879880
}
880881

881-
static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
882-
struct nfs_delegation *delegation)
882+
static void
883+
nfs_mark_return_if_closed_delegation(struct nfs_server *server,
884+
struct nfs_delegation *delegation)
883885
{
884-
set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
885-
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
886+
struct inode *inode;
887+
888+
if (test_bit(NFS_DELEGATION_RETURN, &delegation->flags) ||
889+
test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags))
890+
return;
891+
spin_lock(&delegation->lock);
892+
inode = delegation->inode;
893+
if (!inode)
894+
goto out;
895+
if (list_empty(&NFS_I(inode)->open_files))
896+
nfs_mark_return_delegation(server, delegation);
897+
else
898+
set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
899+
out:
900+
spin_unlock(&delegation->lock);
886901
}
887902

888903
static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
@@ -1276,6 +1291,7 @@ static void nfs_mark_test_expired_delegation(struct nfs_server *server,
12761291
return;
12771292
clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
12781293
set_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
1294+
set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags);
12791295
set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state);
12801296
}
12811297

@@ -1354,6 +1370,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
13541370
nfs4_stateid stateid;
13551371
unsigned long gen = ++server->delegation_gen;
13561372

1373+
if (!test_and_clear_bit(NFS4SERV_DELEGATION_EXPIRED,
1374+
&server->delegation_flags))
1375+
return 0;
13571376
restart:
13581377
rcu_read_lock();
13591378
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
@@ -1383,6 +1402,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
13831402
goto restart;
13841403
}
13851404
nfs_inode_mark_test_expired_delegation(server,inode);
1405+
set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags);
1406+
set_bit(NFS4CLNT_DELEGATION_EXPIRED,
1407+
&server->nfs_client->cl_state);
13861408
iput(inode);
13871409
return -EAGAIN;
13881410
}

fs/nfs/dir.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ static bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx,
666666
{
667667
if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS))
668668
return false;
669+
if (NFS_SERVER(dir)->flags & NFS_MOUNT_FORCE_RDIRPLUS)
670+
return true;
669671
if (ctx->pos == 0 ||
670672
cache_hits + cache_misses > NFS_READDIR_CACHE_USAGE_THRESHOLD)
671673
return true;

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,10 +1154,14 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
11541154
rpc_wake_up(&tbl->slot_tbl_waitq);
11551155
goto reset;
11561156
/* RPC connection errors */
1157+
case -ENETDOWN:
1158+
case -ENETUNREACH:
1159+
if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags))
1160+
return -NFS4ERR_FATAL_IOERROR;
1161+
fallthrough;
11571162
case -ECONNREFUSED:
11581163
case -EHOSTDOWN:
11591164
case -EHOSTUNREACH:
1160-
case -ENETUNREACH:
11611165
case -EIO:
11621166
case -ETIMEDOUT:
11631167
case -EPIPE:
@@ -1183,6 +1187,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
11831187

11841188
/* Retry all errors through either pNFS or MDS except for -EJUKEBOX */
11851189
static int ff_layout_async_handle_error_v3(struct rpc_task *task,
1190+
struct nfs_client *clp,
11861191
struct pnfs_layout_segment *lseg,
11871192
u32 idx)
11881193
{
@@ -1200,6 +1205,11 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task,
12001205
case -EJUKEBOX:
12011206
nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY);
12021207
goto out_retry;
1208+
case -ENETDOWN:
1209+
case -ENETUNREACH:
1210+
if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags))
1211+
return -NFS4ERR_FATAL_IOERROR;
1212+
fallthrough;
12031213
default:
12041214
dprintk("%s DS connection error %d\n", __func__,
12051215
task->tk_status);
@@ -1234,7 +1244,7 @@ static int ff_layout_async_handle_error(struct rpc_task *task,
12341244

12351245
switch (vers) {
12361246
case 3:
1237-
return ff_layout_async_handle_error_v3(task, lseg, idx);
1247+
return ff_layout_async_handle_error_v3(task, clp, lseg, idx);
12381248
case 4:
12391249
return ff_layout_async_handle_error_v4(task, state, clp,
12401250
lseg, idx);
@@ -1264,6 +1274,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
12641274
case -ECONNRESET:
12651275
case -EHOSTDOWN:
12661276
case -EHOSTUNREACH:
1277+
case -ENETDOWN:
12671278
case -ENETUNREACH:
12681279
case -EADDRINUSE:
12691280
case -ENOBUFS:
@@ -1337,6 +1348,9 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
13371348
return task->tk_status;
13381349
case -EAGAIN:
13391350
goto out_eagain;
1351+
case -NFS4ERR_FATAL_IOERROR:
1352+
task->tk_status = -EIO;
1353+
return 0;
13401354
}
13411355

13421356
return 0;
@@ -1507,6 +1521,9 @@ static int ff_layout_write_done_cb(struct rpc_task *task,
15071521
return task->tk_status;
15081522
case -EAGAIN:
15091523
return -EAGAIN;
1524+
case -NFS4ERR_FATAL_IOERROR:
1525+
task->tk_status = -EIO;
1526+
return 0;
15101527
}
15111528

15121529
if (hdr->res.verf->committed == NFS_FILE_SYNC ||
@@ -1551,6 +1568,9 @@ static int ff_layout_commit_done_cb(struct rpc_task *task,
15511568
case -EAGAIN:
15521569
rpc_restart_call_prepare(task);
15531570
return -EAGAIN;
1571+
case -NFS4ERR_FATAL_IOERROR:
1572+
task->tk_status = -EIO;
1573+
return 0;
15541574
}
15551575

15561576
ff_layout_set_layoutcommit(data->inode, data->lseg, data->lwb);

0 commit comments

Comments
 (0)