Skip to content

Commit cbf3a2c

Browse files
committed
Merge tag 'nfs-for-6.6-3' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client fixes from Anna Schumaker: "Stable fixes: - Revert "SUNRPC dont update timeout value on connection reset" - NFSv4: Fix a state manager thread deadlock regression Fixes: - Fix potential NULL pointer dereference in nfs_inode_remove_request() - Fix rare NULL pointer dereference in xs_tcp_tls_setup_socket() - Fix long delay before failing a TLS mount when server does not support TLS - Fix various NFS state manager issues" * tag 'nfs-for-6.6-3' of git://git.linux-nfs.org/projects/anna/linux-nfs: nfs: decrement nrequests counter before releasing the req SUNRPC/TLS: Lock the lower_xprt during the tls handshake Revert "SUNRPC dont update timeout value on connection reset" NFSv4: Fix a state manager thread deadlock regression NFSv4: Fix a nfs4_state_manager() race SUNRPC: Fail quickly when server does not recognize TLS
2 parents 7cccbec + dd1b202 commit cbf3a2c

File tree

7 files changed

+63
-22
lines changed

7 files changed

+63
-22
lines changed

fs/nfs/nfs4proc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode)
1062210622
*/
1062310623
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
1062410624

10625-
nfs4_schedule_state_manager(clp);
10625+
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
10626+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
10627+
wake_up_var(&clp->cl_state);
1062610628
}
1062710629

1062810630
static const struct inode_operations nfs4_dir_inode_operations = {

fs/nfs/nfs4state.c

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
12091209
{
12101210
struct task_struct *task;
12111211
char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
1212+
struct rpc_clnt *clnt = clp->cl_rpcclient;
1213+
bool swapon = false;
12121214

1213-
if (clp->cl_rpcclient->cl_shutdown)
1215+
if (clnt->cl_shutdown)
12141216
return;
12151217

12161218
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
1217-
if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) {
1218-
wake_up_var(&clp->cl_state);
1219-
return;
1219+
1220+
if (atomic_read(&clnt->cl_swapper)) {
1221+
swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE,
1222+
&clp->cl_state);
1223+
if (!swapon) {
1224+
wake_up_var(&clp->cl_state);
1225+
return;
1226+
}
12201227
}
1221-
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
1228+
1229+
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
1230+
return;
1231+
12221232
__module_get(THIS_MODULE);
12231233
refcount_inc(&clp->cl_count);
12241234

@@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
12351245
__func__, PTR_ERR(task));
12361246
if (!nfs_client_init_is_complete(clp))
12371247
nfs_mark_client_ready(clp, PTR_ERR(task));
1248+
if (swapon)
1249+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
12381250
nfs4_clear_state_manager_bit(clp);
1239-
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
12401251
nfs_put_client(clp);
12411252
module_put(THIS_MODULE);
12421253
}
@@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp)
27032714
nfs4_end_drain_session(clp);
27042715
nfs4_clear_state_manager_bit(clp);
27052716

2717+
if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
2718+
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING,
2719+
&clp->cl_state)) {
2720+
memflags = memalloc_nofs_save();
2721+
continue;
2722+
}
2723+
27062724
if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) {
27072725
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
27082726
nfs_client_return_marked_delegations(clp);
@@ -2741,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr)
27412759

27422760
allow_signal(SIGKILL);
27432761
again:
2744-
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
27452762
nfs4_state_manager(clp);
2746-
if (atomic_read(&cl->cl_swapper)) {
2763+
2764+
if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) &&
2765+
!test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) {
27472766
wait_var_event_interruptible(&clp->cl_state,
27482767
test_bit(NFS4CLNT_RUN_MANAGER,
27492768
&clp->cl_state));
2750-
if (atomic_read(&cl->cl_swapper) &&
2751-
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
2769+
if (!atomic_read(&cl->cl_swapper))
2770+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
2771+
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
2772+
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
27522773
goto again;
27532774
/* Either no longer a swapper, or were signalled */
2775+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
27542776
}
2755-
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
27562777

27572778
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
27582779
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
2759-
!test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state))
2780+
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
27602781
goto again;
27612782

27622783
nfs_put_client(clp);

fs/nfs/write.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,8 +802,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
802802
}
803803

804804
if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
805-
nfs_release_request(req);
806805
atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests);
806+
nfs_release_request(req);
807807
}
808808
}
809809

net/sunrpc/auth.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,9 +769,14 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
769769
* @task: controlling RPC task
770770
* @xdr: xdr_stream containing RPC Reply header
771771
*
772-
* On success, @xdr is updated to point past the verifier and
773-
* zero is returned. Otherwise, @xdr is in an undefined state
774-
* and a negative errno is returned.
772+
* Return values:
773+
* %0: Verifier is valid. @xdr now points past the verifier.
774+
* %-EIO: Verifier is corrupted or message ended early.
775+
* %-EACCES: Verifier is intact but not valid.
776+
* %-EPROTONOSUPPORT: Server does not support the requested auth type.
777+
*
778+
* When a negative errno is returned, @xdr is left in an undefined
779+
* state.
775780
*/
776781
int
777782
rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)

net/sunrpc/auth_tls.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr)
129129
if (*p != rpc_auth_null)
130130
return -EIO;
131131
if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len)
132-
return -EIO;
132+
return -EPROTONOSUPPORT;
133133
if (memcmp(str, starttls_token, starttls_len))
134-
return -EIO;
134+
return -EPROTONOSUPPORT;
135135
return 0;
136136
}
137137

net/sunrpc/clnt.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task)
24762476
goto out_exit;
24772477
}
24782478
task->tk_action = call_encode;
2479-
if (status != -ECONNRESET && status != -ECONNABORTED)
2480-
rpc_check_timeout(task);
2479+
rpc_check_timeout(task);
24812480
return;
24822481
out_exit:
24832482
rpc_call_rpcerror(task, status);
@@ -2725,7 +2724,15 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
27252724

27262725
out_verifier:
27272726
trace_rpc_bad_verifier(task);
2728-
goto out_garbage;
2727+
switch (error) {
2728+
case -EPROTONOSUPPORT:
2729+
goto out_err;
2730+
case -EACCES:
2731+
/* Re-encode with a fresh cred */
2732+
fallthrough;
2733+
default:
2734+
goto out_garbage;
2735+
}
27292736

27302737
out_msg_denied:
27312738
error = -EACCES;

net/sunrpc/xprtsock.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
26722672
rcu_read_lock();
26732673
lower_xprt = rcu_dereference(lower_clnt->cl_xprt);
26742674
rcu_read_unlock();
2675+
2676+
if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE))
2677+
goto out_unlock;
2678+
26752679
status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec);
26762680
if (status) {
26772681
trace_rpc_tls_not_started(upper_clnt, upper_xprt);
@@ -2681,6 +2685,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
26812685
status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport);
26822686
if (status)
26832687
goto out_close;
2688+
xprt_release_write(lower_xprt, NULL);
26842689

26852690
trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0);
26862691
if (!xprt_test_and_set_connected(upper_xprt)) {
@@ -2702,6 +2707,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
27022707
return;
27032708

27042709
out_close:
2710+
xprt_release_write(lower_xprt, NULL);
27052711
rpc_shutdown_client(lower_clnt);
27062712

27072713
/* xprt_force_disconnect() wakes tasks with a fixed tk_status code.

0 commit comments

Comments
 (0)