[PATCH 4/4] smb: prevent TIF_NOTIFY_SIGNAL from interrupting

Christian Brauner <[email protected]>
Newsgroups org.kernel.vger.bpf,org.kernel.vger.linux-cifs,org.kernel.vger.linux-fsdevel,org.kvack.linux-mm
Message-ID <[email protected]>
smb_send_kvec() blocks every signal during a send:

	sigfillset(&mask);
	sigprocmask(SIG_BLOCK, &mask, &oldmask);

An incomplete or partial sent would cause the connection to become out
of sync. That in turn would cause the session to be torn down and
reconnected.

In 00be6f26a2a7 ("smb: client: transport: avoid reconnects triggered
by pending task work") smb hand-rolled its own solution. Have it use the
new no_notify_signal_save() critical section instead.

This stops io_uring from cancelling a send in flight but that's just
like it is today and it is bounded by sk_sndtimeo at around 15s.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 fs/smb/client/transport.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index fdf4e50c27ce..05dc20916c27 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -22,7 +22,6 @@
 #include <linux/mempool.h>
 #include <linux/sched/signal.h>
 #include <linux/task_io_accounting_ops.h>
-#include <linux/task_work.h>
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifs_debug.h"
@@ -142,6 +141,7 @@ int
 smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 	      size_t *sent)
 {
+	unsigned int notify_flags;
 	int rc = 0;
 	int retries = 0;
 	struct socket *ssocket = server->ssocket;
@@ -172,15 +172,12 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 		 * after the retries we will kill the socket and
 		 * reconnect which may clear the network problem.
 		 *
-		 * Even if regular signals are masked, EINTR might be
-		 * propagated from sk_stream_wait_memory() to here when
-		 * TIF_NOTIFY_SIGNAL is used for task work. For example,
-		 * certain io_uring completions will use that. Treat
-		 * having EINTR with pending task work the same as EAGAIN
-		 * to avoid unnecessary reconnects.
+		 * Task work must not abort the send, see signal_pending().
 		 */
+		notify_flags = no_notify_signal_save();
 		rc = sock_sendmsg(ssocket, smb_msg);
-		if (rc == -EAGAIN || unlikely(rc == -EINTR && task_work_pending(current))) {
+		no_notify_signal_restore(notify_flags);
+		if (rc == -EAGAIN) {
 			retries++;
 			if (retries >= 14 ||
 			    (!server->noblocksnd && (retries > 2))) {

-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.