[PATCH 6/9] smb/client: add helpers for sending cancel requests

ChenXiaoSong <[email protected]>
Newsgroups org.kernel.vger.linux-cifs
Message-ID <[email protected]>
From: ChenXiaoSong <[email protected]>

SMB cancel requests are sent after the waiter has already been interrupted,
so they need to get onto the wire even when the current task has a pending
signal.

Split the low-level send path so normal requests keep the existing blocking
and signal checks, while cancel requests can ignore the pre-send fatal
signal check and force non-blocking socket sends.

Signed-off-by: ChenXiaoSong <[email protected]>
---
 fs/smb/client/cifsproto.h |  2 ++
 fs/smb/client/transport.c | 49 +++++++++++++++++++++++++++++----------
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index dfbad6bc0a9b..4afe2163ef67 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -109,6 +109,8 @@ int cifs_sync_mid_result(struct mid_q_entry *mid,
 			 struct TCP_Server_Info *server);
 int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 		    struct smb_rqst *rqst);
+int __smb_send_cancel_rqst(struct TCP_Server_Info *server, int num_rqst,
+			   struct smb_rqst *rqst);
 int wait_for_free_request(struct TCP_Server_Info *server, const int flags,
 			  unsigned int *instance);
 int cifs_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index fdf4e50c27ce..652e1e5711ad 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -130,17 +130,18 @@ delete_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 }
 
 /*
- * smb_send_kvec - send an array of kvecs to the server
+ * smb_send_kvec_flags - send an array of kvecs to the server
  * @server:	Server to send the data to
  * @smb_msg:	Message to send
  * @sent:	amount of data sent on socket is stored here
+ * @force_nonblock:	force non-blocking socket sends
  *
- * Our basic "send data to server" function. Should be called with srv_mutex
+ * Our basic "send data to server" helper. Should be called with srv_mutex
  * held. The caller is responsible for handling the results.
  */
-int
-smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
-	      size_t *sent)
+static int
+smb_send_kvec_flags(struct TCP_Server_Info *server, struct msghdr *smb_msg,
+		    size_t *sent, bool force_nonblock)
 {
 	int rc = 0;
 	int retries = 0;
@@ -148,7 +149,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 
 	*sent = 0;
 
-	if (server->noblocksnd)
+	if (server->noblocksnd || force_nonblock)
 		smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
 	else
 		smb_msg->msg_flags = MSG_NOSIGNAL;
@@ -210,6 +211,13 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 	return 0;
 }
 
+int
+smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
+	      size_t *sent)
+{
+	return smb_send_kvec_flags(server, smb_msg, sent, false);
+}
+
 unsigned long
 smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 {
@@ -235,8 +243,10 @@ smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	return buflen;
 }
 
-int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
-		    struct smb_rqst *rqst)
+static int
+__smb_send_rqst_common(struct TCP_Server_Info *server, int num_rqst,
+		       struct smb_rqst *rqst, bool ignore_signal,
+		       bool force_nonblock)
 {
 	int rc;
 	struct kvec *iov;
@@ -263,7 +273,7 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 		goto out;
 
 	rc = -ERESTARTSYS;
-	if (fatal_signal_pending(current)) {
+	if (!ignore_signal && fatal_signal_pending(current)) {
 		cifs_dbg(FYI, "signal pending before send request\n");
 		goto out;
 	}
@@ -293,7 +303,8 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 			.iov_len  = 4
 		};
 		iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, &hiov, 1, 4);
-		rc = smb_send_kvec(server, &smb_msg, &sent);
+		rc = smb_send_kvec_flags(server, &smb_msg, &sent,
+					 force_nonblock);
 		if (rc < 0)
 			goto unmask;
 
@@ -315,7 +326,8 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 
 		iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, iov, n_vec, size);
 
-		rc = smb_send_kvec(server, &smb_msg, &sent);
+		rc = smb_send_kvec_flags(server, &smb_msg, &sent,
+					 force_nonblock);
 		if (rc < 0)
 			goto unmask;
 
@@ -323,7 +335,8 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 
 		if (iov_iter_count(&rqst[j].rq_iter) > 0) {
 			smb_msg.msg_iter = rqst[j].rq_iter;
-			rc = smb_send_kvec(server, &smb_msg, &sent);
+			rc = smb_send_kvec_flags(server, &smb_msg,
+						 &sent, force_nonblock);
 			if (rc < 0)
 				break;
 			total_len += sent;
@@ -382,6 +395,18 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 	return rc;
 }
 
+int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
+		    struct smb_rqst *rqst)
+{
+	return __smb_send_rqst_common(server, num_rqst, rqst, false, false);
+}
+
+int __smb_send_cancel_rqst(struct TCP_Server_Info *server, int num_rqst,
+			   struct smb_rqst *rqst)
+{
+	return __smb_send_rqst_common(server, num_rqst, rqst, true, true);
+}
+
 static int
 smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 	      struct smb_rqst *rqst, int flags)
-- 
2.54.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.