From: Greg Kroah-Hartman Date: Mon, 16 May 2022 12:42:17 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v4.9.315~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=92b56f99235285cc7dc04596b03555a3f277ed20;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: sunrpc-clean-up-scheduling-of-autoclose.patch sunrpc-don-t-call-connect-more-than-once-on-a-tcp-socket.patch sunrpc-ensure-we-flush-any-closed-sockets-before-xs_xprt_free.patch sunrpc-prevent-immediate-close-reconnect.patch --- diff --git a/queue-5.10/series b/queue-5.10/series index 1c8bae4eb6f..81f2b257dcd 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -55,3 +55,7 @@ i40e-i40e_main-fix-a-missing-check-on-list-iterator.patch net-atlantic-always-deep-reset-on-pm-op-fixing-up-my-null-deref-regression.patch cgroup-cpuset-remove-cpus_allowed-mems_allowed-setup-in-cpuset_init_smp.patch drm-vmwgfx-initialize-drm_mode_fb_cmd2.patch +sunrpc-clean-up-scheduling-of-autoclose.patch +sunrpc-prevent-immediate-close-reconnect.patch +sunrpc-don-t-call-connect-more-than-once-on-a-tcp-socket.patch +sunrpc-ensure-we-flush-any-closed-sockets-before-xs_xprt_free.patch diff --git a/queue-5.10/sunrpc-clean-up-scheduling-of-autoclose.patch b/queue-5.10/sunrpc-clean-up-scheduling-of-autoclose.patch new file mode 100644 index 00000000000..ec54f09e37f --- /dev/null +++ b/queue-5.10/sunrpc-clean-up-scheduling-of-autoclose.patch @@ -0,0 +1,71 @@ +From e26d9972720e2484f44cdd94ca4e31cc372ed2ed Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 26 Jul 2021 07:59:24 -0400 +Subject: SUNRPC: Clean up scheduling of autoclose + +From: Trond Myklebust + +commit e26d9972720e2484f44cdd94ca4e31cc372ed2ed upstream. + +Consolidate duplicated code in xprt_force_disconnect() and +xprt_conditional_disconnect(). + +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Meena Shanmugam +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/xprt.c | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -732,6 +732,20 @@ void xprt_disconnect_done(struct rpc_xpr + EXPORT_SYMBOL_GPL(xprt_disconnect_done); + + /** ++ * xprt_schedule_autoclose_locked - Try to schedule an autoclose RPC call ++ * @xprt: transport to disconnect ++ */ ++static void xprt_schedule_autoclose_locked(struct rpc_xprt *xprt) ++{ ++ set_bit(XPRT_CLOSE_WAIT, &xprt->state); ++ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) ++ queue_work(xprtiod_workqueue, &xprt->task_cleanup); ++ else if (xprt->snd_task && !test_bit(XPRT_SND_IS_COOKIE, &xprt->state)) ++ rpc_wake_up_queued_task_set_status(&xprt->pending, ++ xprt->snd_task, -ENOTCONN); ++} ++ ++/** + * xprt_force_disconnect - force a transport to disconnect + * @xprt: transport to disconnect + * +@@ -742,13 +756,7 @@ void xprt_force_disconnect(struct rpc_xp + + /* Don't race with the test_bit() in xprt_clear_locked() */ + spin_lock(&xprt->transport_lock); +- set_bit(XPRT_CLOSE_WAIT, &xprt->state); +- /* Try to schedule an autoclose RPC call */ +- if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) +- queue_work(xprtiod_workqueue, &xprt->task_cleanup); +- else if (xprt->snd_task && !test_bit(XPRT_SND_IS_COOKIE, &xprt->state)) +- rpc_wake_up_queued_task_set_status(&xprt->pending, +- xprt->snd_task, -ENOTCONN); ++ xprt_schedule_autoclose_locked(xprt); + spin_unlock(&xprt->transport_lock); + } + EXPORT_SYMBOL_GPL(xprt_force_disconnect); +@@ -788,11 +796,7 @@ void xprt_conditional_disconnect(struct + goto out; + if (test_bit(XPRT_CLOSING, &xprt->state)) + goto out; +- set_bit(XPRT_CLOSE_WAIT, &xprt->state); +- /* Try to schedule an autoclose RPC call */ +- if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) +- queue_work(xprtiod_workqueue, &xprt->task_cleanup); +- xprt_wake_pending_tasks(xprt, -EAGAIN); ++ xprt_schedule_autoclose_locked(xprt); + out: + spin_unlock(&xprt->transport_lock); + } diff --git a/queue-5.10/sunrpc-don-t-call-connect-more-than-once-on-a-tcp-socket.patch b/queue-5.10/sunrpc-don-t-call-connect-more-than-once-on-a-tcp-socket.patch new file mode 100644 index 00000000000..0a886c176ce --- /dev/null +++ b/queue-5.10/sunrpc-don-t-call-connect-more-than-once-on-a-tcp-socket.patch @@ -0,0 +1,79 @@ +From 89f42494f92f448747bd8a7ab1ae8b5d5520577d Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Wed, 16 Mar 2022 19:10:43 -0400 +Subject: SUNRPC: Don't call connect() more than once on a TCP socket + +From: Trond Myklebust + +commit 89f42494f92f448747bd8a7ab1ae8b5d5520577d upstream. + +Avoid socket state races due to repeated calls to ->connect() using the +same socket. If connect() returns 0 due to the connection having +completed, but we are in fact in a closing state, then we may leave the +XPRT_CONNECTING flag set on the transport. + +Reported-by: Enrico Scholz +Fixes: 3be232f11a3c ("SUNRPC: Prevent immediate close+reconnect") +Signed-off-by: Trond Myklebust +[meenashanmugam: Backported to 5.10: Fixed merge conflict in xs_tcp_setup_socket] +Signed-off-by: Meena Shanmugam +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/sunrpc/xprtsock.h | 1 + + net/sunrpc/xprtsock.c | 21 +++++++++++---------- + 2 files changed, 12 insertions(+), 10 deletions(-) + +--- a/include/linux/sunrpc/xprtsock.h ++++ b/include/linux/sunrpc/xprtsock.h +@@ -89,5 +89,6 @@ struct sock_xprt { + #define XPRT_SOCK_WAKE_WRITE (5) + #define XPRT_SOCK_WAKE_PENDING (6) + #define XPRT_SOCK_WAKE_DISCONNECT (7) ++#define XPRT_SOCK_CONNECT_SENT (8) + + #endif /* _LINUX_SUNRPC_XPRTSOCK_H */ +--- a/net/sunrpc/xprtsock.c ++++ b/net/sunrpc/xprtsock.c +@@ -2260,10 +2260,14 @@ static void xs_tcp_setup_socket(struct w + struct rpc_xprt *xprt = &transport->xprt; + int status = -EIO; + +- if (!sock) { +- sock = xs_create_sock(xprt, transport, +- xs_addr(xprt)->sa_family, SOCK_STREAM, +- IPPROTO_TCP, true); ++ if (xprt_connected(xprt)) ++ goto out; ++ if (test_and_clear_bit(XPRT_SOCK_CONNECT_SENT, ++ &transport->sock_state) || ++ !sock) { ++ xs_reset_transport(transport); ++ sock = xs_create_sock(xprt, transport, xs_addr(xprt)->sa_family, ++ SOCK_STREAM, IPPROTO_TCP, true); + if (IS_ERR(sock)) { + status = PTR_ERR(sock); + goto out; +@@ -2294,6 +2298,7 @@ static void xs_tcp_setup_socket(struct w + break; + case 0: + case -EINPROGRESS: ++ set_bit(XPRT_SOCK_CONNECT_SENT, &transport->sock_state); + case -EALREADY: + xprt_unlock_connect(xprt, transport); + return; +@@ -2345,13 +2350,9 @@ static void xs_connect(struct rpc_xprt * + + WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport)); + +- if (transport->sock != NULL && !xprt_connecting(xprt)) { ++ if (transport->sock != NULL) { + dprintk("RPC: xs_connect delayed xprt %p for %lu " +- "seconds\n", +- xprt, xprt->reestablish_timeout / HZ); +- +- /* Start by resetting any existing state */ +- xs_reset_transport(transport); ++ "seconds\n", xprt, xprt->reestablish_timeout / HZ); + + delay = xprt_reconnect_delay(xprt); + xprt_reconnect_backoff(xprt, XS_TCP_INIT_REEST_TO); diff --git a/queue-5.10/sunrpc-ensure-we-flush-any-closed-sockets-before-xs_xprt_free.patch b/queue-5.10/sunrpc-ensure-we-flush-any-closed-sockets-before-xs_xprt_free.patch new file mode 100644 index 00000000000..c925e7ff4ca --- /dev/null +++ b/queue-5.10/sunrpc-ensure-we-flush-any-closed-sockets-before-xs_xprt_free.patch @@ -0,0 +1,115 @@ +From f00432063db1a0db484e85193eccc6845435b80e Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sun, 3 Apr 2022 15:58:11 -0400 +Subject: SUNRPC: Ensure we flush any closed sockets before xs_xprt_free() + +From: Trond Myklebust + +commit f00432063db1a0db484e85193eccc6845435b80e upstream. + +We must ensure that all sockets are closed before we call xprt_free() +and release the reference to the net namespace. The problem is that +calling fput() will defer closing the socket until delayed_fput() gets +called. +Let's fix the situation by allowing rpciod and the transport teardown +code (which runs on the system wq) to call __fput_sync(), and directly +close the socket. + +Reported-by: Felix Fu +Acked-by: Al Viro +Fixes: a73881c96d73 ("SUNRPC: Fix an Oops in udp_poll()") +Cc: stable@vger.kernel.org # 5.1.x: 3be232f11a3c: SUNRPC: Prevent immediate close+reconnect +Cc: stable@vger.kernel.org # 5.1.x: 89f42494f92f: SUNRPC: Don't call connect() more than once on a TCP socket +Cc: stable@vger.kernel.org # 5.1.x +Signed-off-by: Trond Myklebust +Signed-off-by: Meena Shanmugam +Signed-off-by: Greg Kroah-Hartman +--- + fs/file_table.c | 1 + + include/trace/events/sunrpc.h | 1 - + net/sunrpc/xprt.c | 7 +------ + net/sunrpc/xprtsock.c | 16 +++++++++++++--- + 4 files changed, 15 insertions(+), 10 deletions(-) + +--- a/fs/file_table.c ++++ b/fs/file_table.c +@@ -376,6 +376,7 @@ void __fput_sync(struct file *file) + } + + EXPORT_SYMBOL(fput); ++EXPORT_SYMBOL(__fput_sync); + + void __init files_init(void) + { +--- a/include/trace/events/sunrpc.h ++++ b/include/trace/events/sunrpc.h +@@ -1006,7 +1006,6 @@ DEFINE_RPC_XPRT_LIFETIME_EVENT(connect); + DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_auto); + DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_done); + DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_force); +-DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_cleanup); + DEFINE_RPC_XPRT_LIFETIME_EVENT(destroy); + + DECLARE_EVENT_CLASS(rpc_xprt_event, +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -886,12 +886,7 @@ void xprt_connect(struct rpc_task *task) + if (!xprt_lock_write(xprt, task)) + return; + +- if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state)) { +- trace_xprt_disconnect_cleanup(xprt); +- xprt->ops->close(xprt); +- } +- +- if (!xprt_connected(xprt)) { ++ if (!xprt_connected(xprt) && !test_bit(XPRT_CLOSE_WAIT, &xprt->state)) { + task->tk_rqstp->rq_connect_cookie = xprt->connect_cookie; + rpc_sleep_on_timeout(&xprt->pending, task, NULL, + xprt_request_timeout(task->tk_rqstp)); +--- a/net/sunrpc/xprtsock.c ++++ b/net/sunrpc/xprtsock.c +@@ -871,7 +871,7 @@ static int xs_local_send_request(struct + + /* Close the stream if the previous transmission was incomplete */ + if (xs_send_request_was_aborted(transport, req)) { +- xs_close(xprt); ++ xprt_force_disconnect(xprt); + return -ENOTCONN; + } + +@@ -909,7 +909,7 @@ static int xs_local_send_request(struct + -status); + fallthrough; + case -EPIPE: +- xs_close(xprt); ++ xprt_force_disconnect(xprt); + status = -ENOTCONN; + } + +@@ -1191,6 +1191,16 @@ static void xs_reset_transport(struct so + + if (sk == NULL) + return; ++ /* ++ * Make sure we're calling this in a context from which it is safe ++ * to call __fput_sync(). In practice that means rpciod and the ++ * system workqueue. ++ */ ++ if (!(current->flags & PF_WQ_WORKER)) { ++ WARN_ON_ONCE(1); ++ set_bit(XPRT_CLOSE_WAIT, &xprt->state); ++ return; ++ } + + if (atomic_read(&transport->xprt.swapper)) + sk_clear_memalloc(sk); +@@ -1214,7 +1224,7 @@ static void xs_reset_transport(struct so + mutex_unlock(&transport->recv_mutex); + + trace_rpc_socket_close(xprt, sock); +- fput(filp); ++ __fput_sync(filp); + + xprt_disconnect_done(xprt); + } diff --git a/queue-5.10/sunrpc-prevent-immediate-close-reconnect.patch b/queue-5.10/sunrpc-prevent-immediate-close-reconnect.patch new file mode 100644 index 00000000000..7aeba586150 --- /dev/null +++ b/queue-5.10/sunrpc-prevent-immediate-close-reconnect.patch @@ -0,0 +1,43 @@ +From 3be232f11a3cc9b0ef0795e39fa11bdb8e422a06 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Tue, 26 Oct 2021 18:01:07 -0400 +Subject: SUNRPC: Prevent immediate close+reconnect + +From: Trond Myklebust + +commit 3be232f11a3cc9b0ef0795e39fa11bdb8e422a06 upstream. + +If we have already set up the socket and are waiting for it to connect, +then don't immediately close and retry. + +Signed-off-by: Trond Myklebust +Signed-off-by: Meena Shanmugam +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/xprt.c | 3 ++- + net/sunrpc/xprtsock.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -737,7 +737,8 @@ EXPORT_SYMBOL_GPL(xprt_disconnect_done); + */ + static void xprt_schedule_autoclose_locked(struct rpc_xprt *xprt) + { +- set_bit(XPRT_CLOSE_WAIT, &xprt->state); ++ if (test_and_set_bit(XPRT_CLOSE_WAIT, &xprt->state)) ++ return; + if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) + queue_work(xprtiod_workqueue, &xprt->task_cleanup); + else if (xprt->snd_task && !test_bit(XPRT_SND_IS_COOKIE, &xprt->state)) +--- a/net/sunrpc/xprtsock.c ++++ b/net/sunrpc/xprtsock.c +@@ -2345,7 +2345,7 @@ static void xs_connect(struct rpc_xprt * + + WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport)); + +- if (transport->sock != NULL) { ++ if (transport->sock != NULL && !xprt_connecting(xprt)) { + dprintk("RPC: xs_connect delayed xprt %p for %lu " + "seconds\n", + xprt, xprt->reestablish_timeout / HZ);