mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-14 08:13:56 +08:00
More NFS Client Bugfixes for Linux 6.6-rc
Stable Fix: * Revert "SUNRPC dont update timeout value on connection reset" * NFSv4: Fix a state manager thread deadlock regression Bugfixes: * Fix a potential NULL pointer dereference in nfs_inode_remove_request() * Fix a 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmUcZYIACgkQ18tUv7Cl QOtNyBAA0RaAI4D5Em3/JxmdaqoK8LgSlw3gSup0VoWG1/gyKlt0wW6gDPzffIVK pb5wTMdDVzZmbamll15gvOJYYY4tEVpMGg5unR5LIIhS/5Z5TbGEU3ioO7xsKnTI 0FYtQ0fEXJaPqVLUh3xY/W7Bn2wdehD2bqSfYakddL1C9+cc1XRnxA5BLEL67ZQ4 zlBhI2acv/9eEGZjVYdI8cv+27WvQY+ud21VZrEGPuztZklfwipNBLr3qT2WpwTU vLqp5Py1PydEV7CHIrPtAKhQIuxlYr4m//YXMD4jU4bQuHql0TmUGzJEvfsOzIZn LPEJy2kIA37/Rm92lPeZ0m6E/bwXz8iv7HTFpvgIf6ZIY2PSsVNFZYovhSv/yV8N qoRcpBswi5nYXZ2KoVfjp+J8NQXWjVS/ODoycdCCWVKEjrVh5oFPfYH67jph4o7l E0QaSNKPhy2OHWVgf8hQNJ+Fi34qvxYG1F2RmaTcJybyco1o4jVQ4WJhNGNJbLWH dorEko6n82XPBB9+1Qo2nUqLwNgNdyHmmqBO0OG5tJH3mrIrRPJ8DBjAIWggDGSH pfB2GftuTuXIUvY97PxZlW0Iz1ZKX6NPFS/gtHJizbVGl+E5wttxbPPJNsApA/v1 ZoE2K2cgSsyqTXR6arf55EJZyO4oAnmYEPQLu5jlyV83vQQz/xY= =qUGw -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
cbf3a2cb15
@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode)
|
||||
*/
|
||||
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
||||
|
||||
nfs4_schedule_state_manager(clp);
|
||||
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
wake_up_var(&clp->cl_state);
|
||||
}
|
||||
|
||||
static const struct inode_operations nfs4_dir_inode_operations = {
|
||||
|
@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
|
||||
{
|
||||
struct task_struct *task;
|
||||
char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
|
||||
struct rpc_clnt *clnt = clp->cl_rpcclient;
|
||||
bool swapon = false;
|
||||
|
||||
if (clp->cl_rpcclient->cl_shutdown)
|
||||
if (clnt->cl_shutdown)
|
||||
return;
|
||||
|
||||
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
|
||||
if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) {
|
||||
wake_up_var(&clp->cl_state);
|
||||
return;
|
||||
|
||||
if (atomic_read(&clnt->cl_swapper)) {
|
||||
swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE,
|
||||
&clp->cl_state);
|
||||
if (!swapon) {
|
||||
wake_up_var(&clp->cl_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
|
||||
|
||||
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
|
||||
return;
|
||||
|
||||
__module_get(THIS_MODULE);
|
||||
refcount_inc(&clp->cl_count);
|
||||
|
||||
@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
|
||||
__func__, PTR_ERR(task));
|
||||
if (!nfs_client_init_is_complete(clp))
|
||||
nfs_mark_client_ready(clp, PTR_ERR(task));
|
||||
if (swapon)
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
nfs4_clear_state_manager_bit(clp);
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
nfs_put_client(clp);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||
nfs4_end_drain_session(clp);
|
||||
nfs4_clear_state_manager_bit(clp);
|
||||
|
||||
if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
|
||||
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING,
|
||||
&clp->cl_state)) {
|
||||
memflags = memalloc_nofs_save();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) {
|
||||
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
|
||||
nfs_client_return_marked_delegations(clp);
|
||||
@ -2741,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr)
|
||||
|
||||
allow_signal(SIGKILL);
|
||||
again:
|
||||
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
|
||||
nfs4_state_manager(clp);
|
||||
if (atomic_read(&cl->cl_swapper)) {
|
||||
|
||||
if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) &&
|
||||
!test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) {
|
||||
wait_var_event_interruptible(&clp->cl_state,
|
||||
test_bit(NFS4CLNT_RUN_MANAGER,
|
||||
&clp->cl_state));
|
||||
if (atomic_read(&cl->cl_swapper) &&
|
||||
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
|
||||
if (!atomic_read(&cl->cl_swapper))
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
|
||||
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
|
||||
goto again;
|
||||
/* Either no longer a swapper, or were signalled */
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
}
|
||||
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
|
||||
|
||||
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
|
||||
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
|
||||
!test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state))
|
||||
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
|
||||
goto again;
|
||||
|
||||
nfs_put_client(clp);
|
||||
|
@ -802,8 +802,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
|
||||
nfs_release_request(req);
|
||||
atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests);
|
||||
nfs_release_request(req);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,9 +769,14 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
|
||||
* @task: controlling RPC task
|
||||
* @xdr: xdr_stream containing RPC Reply header
|
||||
*
|
||||
* On success, @xdr is updated to point past the verifier and
|
||||
* zero is returned. Otherwise, @xdr is in an undefined state
|
||||
* and a negative errno is returned.
|
||||
* Return values:
|
||||
* %0: Verifier is valid. @xdr now points past the verifier.
|
||||
* %-EIO: Verifier is corrupted or message ended early.
|
||||
* %-EACCES: Verifier is intact but not valid.
|
||||
* %-EPROTONOSUPPORT: Server does not support the requested auth type.
|
||||
*
|
||||
* When a negative errno is returned, @xdr is left in an undefined
|
||||
* state.
|
||||
*/
|
||||
int
|
||||
rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
|
||||
|
@ -129,9 +129,9 @@ static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr)
|
||||
if (*p != rpc_auth_null)
|
||||
return -EIO;
|
||||
if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len)
|
||||
return -EIO;
|
||||
return -EPROTONOSUPPORT;
|
||||
if (memcmp(str, starttls_token, starttls_len))
|
||||
return -EIO;
|
||||
return -EPROTONOSUPPORT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task)
|
||||
goto out_exit;
|
||||
}
|
||||
task->tk_action = call_encode;
|
||||
if (status != -ECONNRESET && status != -ECONNABORTED)
|
||||
rpc_check_timeout(task);
|
||||
rpc_check_timeout(task);
|
||||
return;
|
||||
out_exit:
|
||||
rpc_call_rpcerror(task, status);
|
||||
@ -2725,7 +2724,15 @@ out_unparsable:
|
||||
|
||||
out_verifier:
|
||||
trace_rpc_bad_verifier(task);
|
||||
goto out_garbage;
|
||||
switch (error) {
|
||||
case -EPROTONOSUPPORT:
|
||||
goto out_err;
|
||||
case -EACCES:
|
||||
/* Re-encode with a fresh cred */
|
||||
fallthrough;
|
||||
default:
|
||||
goto out_garbage;
|
||||
}
|
||||
|
||||
out_msg_denied:
|
||||
error = -EACCES;
|
||||
|
@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
|
||||
rcu_read_lock();
|
||||
lower_xprt = rcu_dereference(lower_clnt->cl_xprt);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE))
|
||||
goto out_unlock;
|
||||
|
||||
status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec);
|
||||
if (status) {
|
||||
trace_rpc_tls_not_started(upper_clnt, upper_xprt);
|
||||
@ -2681,6 +2685,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
|
||||
status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport);
|
||||
if (status)
|
||||
goto out_close;
|
||||
xprt_release_write(lower_xprt, NULL);
|
||||
|
||||
trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0);
|
||||
if (!xprt_test_and_set_connected(upper_xprt)) {
|
||||
@ -2702,6 +2707,7 @@ out_unlock:
|
||||
return;
|
||||
|
||||
out_close:
|
||||
xprt_release_write(lower_xprt, NULL);
|
||||
rpc_shutdown_client(lower_clnt);
|
||||
|
||||
/* xprt_force_disconnect() wakes tasks with a fixed tk_status code.
|
||||
|
Loading…
Reference in New Issue
Block a user