]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 May 2022 12:42:17 +0000 (14:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 May 2022 12:42:17 +0000 (14:42 +0200)
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

queue-5.10/series
queue-5.10/sunrpc-clean-up-scheduling-of-autoclose.patch [new file with mode: 0644]
queue-5.10/sunrpc-don-t-call-connect-more-than-once-on-a-tcp-socket.patch [new file with mode: 0644]
queue-5.10/sunrpc-ensure-we-flush-any-closed-sockets-before-xs_xprt_free.patch [new file with mode: 0644]
queue-5.10/sunrpc-prevent-immediate-close-reconnect.patch [new file with mode: 0644]

index 1c8bae4eb6f0581bf1fad999df3ebf0df7e7a556..81f2b257dcd675324c31ba301ae7048bd6d272ec 100644 (file)
@@ -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 (file)
index 0000000..ec54f09
--- /dev/null
@@ -0,0 +1,71 @@
+From e26d9972720e2484f44cdd94ca4e31cc372ed2ed Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+Date: Mon, 26 Jul 2021 07:59:24 -0400
+Subject: SUNRPC: Clean up scheduling of autoclose
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+commit e26d9972720e2484f44cdd94ca4e31cc372ed2ed upstream.
+
+Consolidate duplicated code in xprt_force_disconnect() and
+xprt_conditional_disconnect().
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Meena Shanmugam <meenashanmugam@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0a886c1
--- /dev/null
@@ -0,0 +1,79 @@
+From 89f42494f92f448747bd8a7ab1ae8b5d5520577d Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+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 <trond.myklebust@hammerspace.com>
+
+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 <enrico.scholz@sigma-chemnitz.de>
+Fixes: 3be232f11a3c ("SUNRPC: Prevent immediate close+reconnect")
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+[meenashanmugam: Backported to 5.10: Fixed merge conflict in xs_tcp_setup_socket]
+Signed-off-by: Meena Shanmugam <meenashanmugam@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..c925e7f
--- /dev/null
@@ -0,0 +1,115 @@
+From f00432063db1a0db484e85193eccc6845435b80e Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+Date: Sun, 3 Apr 2022 15:58:11 -0400
+Subject: SUNRPC: Ensure we flush any closed sockets before xs_xprt_free()
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+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 <foyjog@gmail.com>
+Acked-by: Al Viro <viro@zeniv.linux.org.uk>
+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 <trond.myklebust@hammerspace.com>
+Signed-off-by: Meena Shanmugam <meenashanmugam@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7aeba58
--- /dev/null
@@ -0,0 +1,43 @@
+From 3be232f11a3cc9b0ef0795e39fa11bdb8e422a06 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+Date: Tue, 26 Oct 2021 18:01:07 -0400
+Subject: SUNRPC: Prevent immediate close+reconnect
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+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 <trond.myklebust@hammerspace.com>
+Signed-off-by: Meena Shanmugam <meenashanmugam@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);