[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