All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
@ 2011-08-26 19:06 Jeff Layton
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

This patchset does a fairly major cleanup and overhaul of the receive
codepath for cifs. Aside from basic cleanup, there are two main goals:

1) allow the receive codepath to identify the mid before receiving all
of the data for a particular SMB.

...and in turn...

2) add the ability for certain calls to receive their responses into
their into their own set of buffers.

These two changes allow cifs to break the CIFSMaxBufSize barrier for
receives. This patchset just adds the necessary infrastructure to do
the above.

A separate patchset will follow that will overhaul cifs_readpages to use
this infrastructure to allow for a larger rsize.

Jeff Layton (16):
  cifs: clean up checkSMB
  cifs: consolidate signature generating code
  cifs: trivial: remove obsolete comment
  cifs: make smb_msg local to read_from_socket
  cifs: check for unresponsive server every time we call kernel_recvmsg
  cifs: simplify read_from_socket
  cifs: turn read_from_socket into a wrapper around a vectorized
    version
  cifs: keep a reusable kvec array for receives
  cifs: clean up check_rfc1002_header
  cifs: add a third receive phase to cifs_demultiplex_thread
  cifs: move mid finding into separate routine
  cifs: eliminate is_multi_rsp parm to find_cifs_mid
  cifs: move buffer pointers into TCP_Server_Info
  cifs: find mid earlier in receive codepath
  cifs: break out 3rd receive phase into separate function
  cifs: add a callback function to receive the rest of the frame

 fs/cifs/cifsencrypt.c |  103 ++--------
 fs/cifs/cifsglob.h    |   29 +++-
 fs/cifs/cifsproto.h   |    7 +-
 fs/cifs/cifssmb.c     |    5 +-
 fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
 fs/cifs/misc.c        |   51 +++---
 fs/cifs/transport.c   |   16 +-
 7 files changed, 391 insertions(+), 339 deletions(-)

-- 
1.7.6

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 01/16] cifs: clean up checkSMB
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 02/16] cifs: consolidate signature generating code Jeff Layton
                     ` (15 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

The variable names in this function are so ambiguous that it's very
difficult to know what it's doing. Rename them to make it a bit more
clear.

Also, remove a redundant length check. cifsd checks to make sure that
the rfclen isn't larger than the maximum frame size when it does the
receive.

Finally, change checkSMB to return a real error code (-EIO) when
it finds an error. That will help simplify some coming changes in the
callers.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/misc.c |   51 +++++++++++++++++++++++++--------------------------
 1 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 7c16933..4a1801b 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -420,19 +420,22 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
 }
 
 int
-checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
+checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int total_read)
 {
-	__u32 len = be32_to_cpu(smb->smb_buf_length);
+	__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
 	__u32 clc_len;  /* calculated length */
-	cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len);
+	cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x",
+		total_read, rfclen);
 
-	if (length < 2 + sizeof(struct smb_hdr)) {
-		if ((length >= sizeof(struct smb_hdr) - 1)
+	/* is this frame too small to even get to a BCC? */
+	if (total_read < 2 + sizeof(struct smb_hdr)) {
+		if ((total_read >= sizeof(struct smb_hdr) - 1)
 			    && (smb->Status.CifsError != 0)) {
+			/* it's an error return */
 			smb->WordCount = 0;
 			/* some error cases do not return wct and bcc */
 			return 0;
-		} else if ((length == sizeof(struct smb_hdr) + 1) &&
+		} else if ((total_read == sizeof(struct smb_hdr) + 1) &&
 				(smb->WordCount == 0)) {
 			char *tmp = (char *)smb;
 			/* Need to work around a bug in two servers here */
@@ -452,39 +455,35 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
 		} else {
 			cERROR(1, "Length less than smb header size");
 		}
-		return 1;
-	}
-	if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-		cERROR(1, "smb length greater than MaxBufSize, mid=%d",
-				   smb->Mid);
-		return 1;
+		return -EIO;
 	}
 
+	/* otherwise, there is enough to get to the BCC */
 	if (check_smb_hdr(smb, mid))
-		return 1;
+		return -EIO;
 	clc_len = smbCalcSize(smb);
 
-	if (4 + len != length) {
+	if (4 + rfclen != total_read) {
 		cERROR(1, "Length read does not match RFC1001 length %d",
-			   len);
-		return 1;
+				rfclen);
+		return -EIO;
 	}
 
-	if (4 + len != clc_len) {
+	if (4 + rfclen != clc_len) {
 		/* check if bcc wrapped around for large read responses */
-		if ((len > 64 * 1024) && (len > clc_len)) {
+		if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
 			/* check if lengths match mod 64K */
-			if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
+			if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
 				return 0; /* bcc wrapped */
 		}
 		cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u",
-				clc_len, 4 + len, smb->Mid);
+				clc_len, 4 + rfclen, smb->Mid);
 
-		if (4 + len < clc_len) {
+		if (4 + rfclen < clc_len) {
 			cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u",
-					len, smb->Mid);
-			return 1;
-		} else if (len > clc_len + 512) {
+					rfclen, smb->Mid);
+			return -EIO;
+		} else if (rfclen > clc_len + 512) {
 			/*
 			 * Some servers (Windows XP in particular) send more
 			 * data than the lengths in the SMB packet would
@@ -495,8 +494,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
 			 * data to 512 bytes.
 			 */
 			cERROR(1, "RFC1001 size %u more than 512 bytes larger "
-				  "than SMB for mid=%u", len, smb->Mid);
-			return 1;
+				  "than SMB for mid=%u", rfclen, smb->Mid);
+			return -EIO;
 		}
 	}
 	return 0;
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 02/16] cifs: consolidate signature generating code
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2011-08-26 19:06   ` [PATCH 01/16] cifs: clean up checkSMB Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 03/16] cifs: trivial: remove obsolete comment Jeff Layton
                     ` (14 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

We have two versions of signature generating code. A vectorized and
non-vectorized version. Eliminate a large chunk of cut-and-paste
code by turning the non-vectorized version into a wrapper around the
vectorized one.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsencrypt.c |  103 ++++++++++---------------------------------------
 fs/cifs/cifsproto.h   |    2 +-
 fs/cifs/transport.c   |   11 ++++-
 3 files changed, 30 insertions(+), 86 deletions(-)

diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index f11dfb6..cf9b338 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,83 +37,8 @@
  * the sequence number before this function is called. Also, this function
  * should be called with the server->srv_mutex held.
  */
-static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
-				struct TCP_Server_Info *server, char *signature)
-{
-	int rc;
-
-	if (cifs_pdu == NULL || signature == NULL || server == NULL)
-		return -EINVAL;
-
-	if (!server->secmech.sdescmd5) {
-		cERROR(1, "%s: Can't generate signature\n", __func__);
-		return -1;
-	}
-
-	rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
-	if (rc) {
-		cERROR(1, "%s: Could not init md5\n", __func__);
-		return rc;
-	}
-
-	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
-		server->session_key.response, server->session_key.len);
-	if (rc) {
-		cERROR(1, "%s: Could not update with response\n", __func__);
-		return rc;
-	}
-
-	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
-		cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
-	if (rc) {
-		cERROR(1, "%s: Could not update with payload\n", __func__);
-		return rc;
-	}
-
-	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
-	if (rc)
-		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
-
-	return rc;
-}
-
-/* must be called with server->srv_mutex held */
-int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
-		  __u32 *pexpected_response_sequence_number)
-{
-	int rc = 0;
-	char smb_signature[20];
-
-	if ((cifs_pdu == NULL) || (server == NULL))
-		return -EINVAL;
-
-	if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
-	    server->tcpStatus == CifsNeedNegotiate)
-		return rc;
-
-	if (!server->session_estab) {
-		memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
-		return rc;
-	}
-
-	cifs_pdu->Signature.Sequence.SequenceNumber =
-			cpu_to_le32(server->sequence_number);
-	cifs_pdu->Signature.Sequence.Reserved = 0;
-
-	*pexpected_response_sequence_number = server->sequence_number++;
-	server->sequence_number++;
-
-	rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
-	if (rc)
-		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
-	else
-		memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
-
-	return rc;
-}
-
-static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
-				struct TCP_Server_Info *server, char *signature)
+static int cifs_calc_signature(const struct kvec *iov, int n_vec,
+			struct TCP_Server_Info *server, char *signature)
 {
 	int i;
 	int rc;
@@ -179,7 +104,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
 {
 	int rc = 0;
 	char smb_signature[20];
-	struct smb_hdr *cifs_pdu = iov[0].iov_base;
+	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
 
 	if ((cifs_pdu == NULL) || (server == NULL))
 		return -EINVAL;
@@ -200,7 +125,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
 	*pexpected_response_sequence_number = server->sequence_number++;
 	server->sequence_number++;
 
-	rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
+	rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
 	if (rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
 	else
@@ -209,13 +134,27 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
 	return rc;
 }
 
-int cifs_verify_signature(struct smb_hdr *cifs_pdu,
+/* must be called with server->srv_mutex held */
+int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
+		  __u32 *pexpected_response_sequence_number)
+{
+	struct kvec iov;
+
+	iov.iov_base = cifs_pdu;
+	iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
+
+	return cifs_sign_smb2(&iov, 1, server,
+			      pexpected_response_sequence_number);
+}
+
+int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
 			  struct TCP_Server_Info *server,
 			  __u32 expected_sequence_number)
 {
 	unsigned int rc;
 	char server_response_sig[8];
 	char what_we_think_sig_should_be[20];
+	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
 
 	if (cifs_pdu == NULL || server == NULL)
 		return -EINVAL;
@@ -247,8 +186,8 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
 	mutex_lock(&server->srv_mutex);
-	rc = cifs_calculate_signature(cifs_pdu, server,
-		what_we_think_sig_should_be);
+	rc = cifs_calc_signature(iov, nr_iov, server,
+				 what_we_think_sig_should_be);
 	mutex_unlock(&server->srv_mutex);
 
 	if (rc)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 8df28e9..03dc945 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -380,7 +380,7 @@ extern void tconInfoFree(struct cifs_tcon *);
 extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
 extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
-extern int cifs_verify_signature(struct smb_hdr *,
+extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
 				 struct TCP_Server_Info *server,
 				__u32 expected_sequence_number);
 extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index a30c7e9..316d4cb 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -500,13 +500,18 @@ int
 cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 		   bool log_error)
 {
-	dump_smb(mid->resp_buf,
-		 min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length)));
+	unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4;
+
+	dump_smb(mid->resp_buf, min_t(u32, 92, len));
 
 	/* convert the length into a more usable form */
 	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
+		struct kvec iov;
+
+		iov.iov_base = mid->resp_buf;
+		iov.iov_len = len;
 		/* FIXME: add code to kill session */
-		if (cifs_verify_signature(mid->resp_buf, server,
+		if (cifs_verify_signature(&iov, 1, server,
 					  mid->sequence_number + 1) != 0)
 			cERROR(1, "Unexpected SMB signature");
 	}
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 03/16] cifs: trivial: remove obsolete comment
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2011-08-26 19:06   ` [PATCH 01/16] cifs: clean up checkSMB Jeff Layton
  2011-08-26 19:06   ` [PATCH 02/16] cifs: consolidate signature generating code Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 04/16] cifs: make smb_msg local to read_from_socket Jeff Layton
                     ` (13 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0ffba09..55efd1d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -694,12 +694,6 @@ incomplete_rcv:
 		 * The right amount was read from socket - 4 bytes,
 		 * so we can now interpret the length field.
 		 */
-
-		/*
-		 * Note that RFC 1001 length is big endian on the wire,
-		 * but we convert it here so it is always manipulated
-		 * as host byte order.
-		 */
 		pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
 
 		cFYI(1, "rfc1002 length 0x%x", pdu_length+4);
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 04/16] cifs: make smb_msg local to read_from_socket
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 03/16] cifs: trivial: remove obsolete comment Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 05/16] cifs: check for unresponsive server every time we call kernel_recvmsg Jeff Layton
                     ` (12 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

If msg_controllen is 0, then the socket layer should never touch these
fields. Thus, there's no need to continually reset them. Also, there's
no need to keep this field on the stack for the demultiplex thread, just
make it a local variable in read_from_socket.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   17 ++++++++---------
 1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 55efd1d..012d970 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -359,16 +359,20 @@ allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
 }
 
 static int
-read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg,
+read_from_socket(struct TCP_Server_Info *server,
 		 struct kvec *iov, unsigned int to_read,
 		 unsigned int *ptotal_read, bool is_header_read)
 {
 	int length, rc = 0;
 	unsigned int total_read;
+	struct msghdr smb_msg;
 	char *buf = iov->iov_base;
 
+	smb_msg.msg_control = NULL;
+	smb_msg.msg_controllen = 0;
+
 	for (total_read = 0; total_read < to_read; total_read += length) {
-		length = kernel_recvmsg(server->ssocket, smb_msg, iov, 1,
+		length = kernel_recvmsg(server->ssocket, &smb_msg, iov, 1,
 					to_read - total_read, 0);
 		if (server->tcpStatus == CifsExiting) {
 			/* then will exit */
@@ -397,8 +401,6 @@ read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 				iov->iov_base = (to_read - total_read) +
 						buf;
 				iov->iov_len = to_read - total_read;
-				smb_msg->msg_control = NULL;
-				smb_msg->msg_controllen = 0;
 				rc = 3;
 			} else
 				rc = 1;
@@ -634,7 +636,6 @@ cifs_demultiplex_thread(void *p)
 	unsigned int pdu_length, total_read;
 	char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
 	struct smb_hdr *smb_buffer = NULL;
-	struct msghdr smb_msg;
 	struct kvec iov;
 	struct task_struct *task_to_wake = NULL;
 	struct mid_q_entry *mid_entry;
@@ -665,8 +666,6 @@ cifs_demultiplex_thread(void *p)
 		buf = smallbuf;
 		iov.iov_base = buf;
 		iov.iov_len = 4;
-		smb_msg.msg_control = NULL;
-		smb_msg.msg_controllen = 0;
 		pdu_length = 4; /* enough to get RFC1001 header */
 
 incomplete_rcv:
@@ -681,7 +680,7 @@ incomplete_rcv:
 			continue;
 		}
 
-		rc = read_from_socket(server, &smb_msg, &iov, pdu_length,
+		rc = read_from_socket(server, &iov, pdu_length,
 				      &total_read, true /* header read */);
 		if (rc == 3)
 			goto incomplete_rcv;
@@ -710,7 +709,7 @@ incomplete_rcv:
 
 		iov.iov_base = 4 + buf;
 		iov.iov_len = pdu_length;
-		rc = read_from_socket(server, &smb_msg, &iov, pdu_length,
+		rc = read_from_socket(server, &iov, pdu_length,
 				      &total_read, false);
 		if (rc == 2)
 			break;
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 05/16] cifs: check for unresponsive server every time we call kernel_recvmsg
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (3 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 04/16] cifs: make smb_msg local to read_from_socket Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 06/16] cifs: simplify read_from_socket Jeff Layton
                     ` (11 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

If the server stops sending data while in the middle of sending a
response then we still want to reconnect it if it doesn't come back.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   33 ++++++++++++++++++++++-----------
 1 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 012d970..e899fec 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -358,6 +358,23 @@ allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
 	return true;
 }
 
+static bool
+server_unresponsive(struct TCP_Server_Info *server)
+{
+	if (echo_retries > 0 && server->tcpStatus == CifsGood &&
+	    time_after(jiffies, server->lstrp +
+				(echo_retries * SMB_ECHO_INTERVAL))) {
+		cERROR(1, "Server %s has not responded in %d seconds. "
+			  "Reconnecting...", server->hostname,
+			  (echo_retries * SMB_ECHO_INTERVAL / HZ));
+		cifs_reconnect(server);
+		wake_up(&server->response_q);
+		return true;
+	}
+
+	return false;
+}
+
 static int
 read_from_socket(struct TCP_Server_Info *server,
 		 struct kvec *iov, unsigned int to_read,
@@ -372,6 +389,11 @@ read_from_socket(struct TCP_Server_Info *server,
 	smb_msg.msg_controllen = 0;
 
 	for (total_read = 0; total_read < to_read; total_read += length) {
+		if (server_unresponsive(server)) {
+			rc = 1;
+			break;
+		}
+
 		length = kernel_recvmsg(server->ssocket, &smb_msg, iov, 1,
 					to_read - total_read, 0);
 		if (server->tcpStatus == CifsExiting) {
@@ -669,17 +691,6 @@ cifs_demultiplex_thread(void *p)
 		pdu_length = 4; /* enough to get RFC1001 header */
 
 incomplete_rcv:
-		if (echo_retries > 0 && server->tcpStatus == CifsGood &&
-		    time_after(jiffies, server->lstrp +
-					(echo_retries * SMB_ECHO_INTERVAL))) {
-			cERROR(1, "Server %s has not responded in %d seconds. "
-				  "Reconnecting...", server->hostname,
-				  (echo_retries * SMB_ECHO_INTERVAL / HZ));
-			cifs_reconnect(server);
-			wake_up(&server->response_q);
-			continue;
-		}
-
 		rc = read_from_socket(server, &iov, pdu_length,
 				      &total_read, true /* header read */);
 		if (rc == 3)
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 06/16] cifs: simplify read_from_socket
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (4 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 05/16] cifs: check for unresponsive server every time we call kernel_recvmsg Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 07/16] cifs: turn read_from_socket into a wrapper around a vectorized version Jeff Layton
                     ` (10 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Move the iovec handling entirely into read_from_socket. That simplifies
the code and gets rid of the special handling for header reads. With
this we can also get rid of the "goto incomplete_rcv" label in the main
demultiplex thread function since we can now treat header and non-header
receives the same way.

Also, make it return an int (since we'll never receive enough to worry
about the sign bit anyway), and simply make it return the amount of bytes
read or a negative error code.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   77 ++++++++++++++++------------------------------------
 1 files changed, 24 insertions(+), 53 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e899fec..358e0b0 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -376,35 +376,33 @@ server_unresponsive(struct TCP_Server_Info *server)
 }
 
 static int
-read_from_socket(struct TCP_Server_Info *server,
-		 struct kvec *iov, unsigned int to_read,
-		 unsigned int *ptotal_read, bool is_header_read)
+read_from_socket(struct TCP_Server_Info *server, char *buf,
+		 unsigned int to_read)
 {
-	int length, rc = 0;
-	unsigned int total_read;
+	int length = 0;
+	int total_read;
 	struct msghdr smb_msg;
-	char *buf = iov->iov_base;
+	struct kvec iov;
 
 	smb_msg.msg_control = NULL;
 	smb_msg.msg_controllen = 0;
 
-	for (total_read = 0; total_read < to_read; total_read += length) {
+	for (total_read = 0; to_read; total_read += length, to_read -= length) {
 		if (server_unresponsive(server)) {
-			rc = 1;
+			total_read = -EAGAIN;
 			break;
 		}
 
-		length = kernel_recvmsg(server->ssocket, &smb_msg, iov, 1,
-					to_read - total_read, 0);
+		iov.iov_base = buf + total_read;
+		iov.iov_len = to_read;
+		length = kernel_recvmsg(server->ssocket, &smb_msg, &iov, 1,
+					to_read, 0);
 		if (server->tcpStatus == CifsExiting) {
-			/* then will exit */
-			rc = 2;
+			total_read = -ESHUTDOWN;
 			break;
 		} else if (server->tcpStatus == CifsNeedReconnect) {
 			cifs_reconnect(server);
-			/* Reconnect wakes up rspns q */
-			/* Now we will reread sock */
-			rc = 1;
+			total_read = -EAGAIN;
 			break;
 		} else if (length == -ERESTARTSYS ||
 			   length == -EAGAIN ||
@@ -416,28 +414,16 @@ read_from_socket(struct TCP_Server_Info *server,
 			 */
 			usleep_range(1000, 2000);
 			length = 0;
-			if (!is_header_read)
-				continue;
-			/* Special handling for header read */
-			if (total_read) {
-				iov->iov_base = (to_read - total_read) +
-						buf;
-				iov->iov_len = to_read - total_read;
-				rc = 3;
-			} else
-				rc = 1;
-			break;
+			continue;
 		} else if (length <= 0) {
-			cERROR(1, "Received no data, expecting %d",
-			       to_read - total_read);
+			cERROR(1, "Received no data or error: expecting %d "
+				  "got %d", to_read, length);
 			cifs_reconnect(server);
-			rc = 1;
+			total_read = -EAGAIN;
 			break;
 		}
 	}
-
-	*ptotal_read = total_read;
-	return rc;
+	return total_read;
 }
 
 static bool
@@ -658,12 +644,10 @@ cifs_demultiplex_thread(void *p)
 	unsigned int pdu_length, total_read;
 	char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
 	struct smb_hdr *smb_buffer = NULL;
-	struct kvec iov;
 	struct task_struct *task_to_wake = NULL;
 	struct mid_q_entry *mid_entry;
 	bool isLargeBuf = false;
 	bool isMultiRsp = false;
-	int rc;
 
 	current->flags |= PF_MEMALLOC;
 	cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
@@ -686,19 +670,12 @@ cifs_demultiplex_thread(void *p)
 		isMultiRsp = false;
 		smb_buffer = (struct smb_hdr *)smallbuf;
 		buf = smallbuf;
-		iov.iov_base = buf;
-		iov.iov_len = 4;
 		pdu_length = 4; /* enough to get RFC1001 header */
 
-incomplete_rcv:
-		rc = read_from_socket(server, &iov, pdu_length,
-				      &total_read, true /* header read */);
-		if (rc == 3)
-			goto incomplete_rcv;
-		else if (rc == 2)
-			break;
-		else if (rc == 1)
+		length = read_from_socket(server, buf, pdu_length);
+		if (length < 0)
 			continue;
+		total_read = length;
 
 		/*
 		 * The right amount was read from socket - 4 bytes,
@@ -718,16 +695,10 @@ incomplete_rcv:
 			buf = bigbuf;
 		}
 
-		iov.iov_base = 4 + buf;
-		iov.iov_len = pdu_length;
-		rc = read_from_socket(server, &iov, pdu_length,
-				      &total_read, false);
-		if (rc == 2)
-			break;
-		else if (rc == 1)
+		length = read_from_socket(server, buf + 4, pdu_length);
+		if (length < 0)
 			continue;
-
-		total_read += 4; /* account for rfc1002 hdr */
+		total_read += length;
 
 		dump_smb(smb_buffer, total_read);
 
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 07/16] cifs: turn read_from_socket into a wrapper around a vectorized version
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (5 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 06/16] cifs: simplify read_from_socket Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 08/16] cifs: keep a reusable kvec array for receives Jeff Layton
                     ` (9 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Eventually we'll want to allow cifsd to read data directly into the
pagecache. In order to do that we'll need a routine that can take a
kvec array and pass that directly to kernel_recvmsg.

Unfortunately though, the kernel's recvmsg routines modify the kvec
array that gets passed in, so we need to use a copy of the kvec array
and refresh that copy on each pass through the loop.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 358e0b0..3ff3fab 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -375,14 +375,58 @@ server_unresponsive(struct TCP_Server_Info *server)
 	return false;
 }
 
+/*
+ * kvec_array_setup - clone a kvec array, and advance into it
+ * @new:	pointer to memory for cloned array
+ * @iov:	pointer to original array
+ * @nr_segs:	number of members in original array
+ * @bytes:	number of bytes to advance into the cloned array
+ *
+ * This function will copy the array provided in iov to a section of memory
+ * and advance the specified number of bytes into the new array. It returns
+ * the number of segments in the new array. "new" must be at least as big as
+ * the original iov array.
+ */
+static unsigned int
+kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
+		size_t bytes)
+{
+	size_t base = 0;
+
+	while (bytes || !iov->iov_len) {
+		int copy = min(bytes, iov->iov_len);
+
+		bytes -= copy;
+		base += copy;
+		if (iov->iov_len == base) {
+			iov++;
+			nr_segs--;
+			base = 0;
+		}
+	}
+	memcpy(new, iov, sizeof(*iov) * nr_segs);
+	new->iov_base += base;
+	new->iov_len -= base;
+	return nr_segs;
+}
+
 static int
-read_from_socket(struct TCP_Server_Info *server, char *buf,
-		 unsigned int to_read)
+readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
+		  unsigned int nr_segs, unsigned int to_read)
 {
 	int length = 0;
 	int total_read;
+	unsigned int segs;
 	struct msghdr smb_msg;
-	struct kvec iov;
+	struct kvec *iov;
+
+	/*
+	 * FIXME: allocation here may cause deadlocks under memory pressure.
+	 * Switch this to use a fixed, per-socket buffer.
+	 */
+	iov = kmalloc(sizeof(*iov_orig) * nr_segs, GFP_KERNEL);
+	if (!iov)
+		return -ENOMEM;
 
 	smb_msg.msg_control = NULL;
 	smb_msg.msg_controllen = 0;
@@ -393,10 +437,11 @@ read_from_socket(struct TCP_Server_Info *server, char *buf,
 			break;
 		}
 
-		iov.iov_base = buf + total_read;
-		iov.iov_len = to_read;
-		length = kernel_recvmsg(server->ssocket, &smb_msg, &iov, 1,
-					to_read, 0);
+		segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
+
+		length = kernel_recvmsg(server->ssocket, &smb_msg,
+					iov, segs, to_read, 0);
+
 		if (server->tcpStatus == CifsExiting) {
 			total_read = -ESHUTDOWN;
 			break;
@@ -423,9 +468,22 @@ read_from_socket(struct TCP_Server_Info *server, char *buf,
 			break;
 		}
 	}
+	kfree(iov);
 	return total_read;
 }
 
+static int
+read_from_socket(struct TCP_Server_Info *server, char *buf,
+		 unsigned int to_read)
+{
+	struct kvec iov;
+
+	iov.iov_base = buf;
+	iov.iov_len = to_read;
+
+	return readv_from_socket(server, &iov, 1, to_read);
+}
+
 static bool
 check_rfc1002_header(struct TCP_Server_Info *server, char *buf)
 {
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 08/16] cifs: keep a reusable kvec array for receives
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (6 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 07/16] cifs: turn read_from_socket into a wrapper around a vectorized version Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 09/16] cifs: clean up check_rfc1002_header Jeff Layton
                     ` (8 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Having to continually allocate a new kvec array is expensive. Allocate
one that's big enough, and only reallocate it as needed.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsglob.h |    2 ++
 fs/cifs/connect.c  |   26 ++++++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 95dad9d..7d93c62 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -287,6 +287,8 @@ struct TCP_Server_Info {
 	bool	sec_kerberos;		/* supports plain Kerberos */
 	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
 	struct delayed_work	echo; /* echo ping workqueue job */
+	struct kvec *iov;	/* reusable kvec array for receives */
+	unsigned int nr_iov;	/* number of kvecs in array */
 #ifdef CONFIG_CIFS_FSCACHE
 	struct fscache_cookie   *fscache; /* client index cache cookie */
 #endif
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3ff3fab..f7bd9ba 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -410,6 +410,24 @@ kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
 	return nr_segs;
 }
 
+static struct kvec *
+get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
+{
+	struct kvec *new_iov;
+
+	if (server->iov && nr_segs <= server->nr_iov)
+		return server->iov;
+
+	/* not big enough -- allocate a new one and release the old */
+	new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_KERNEL);
+	if (new_iov) {
+		kfree(server->iov);
+		server->iov = new_iov;
+		server->nr_iov = nr_segs;
+	}
+	return new_iov;
+}
+
 static int
 readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
 		  unsigned int nr_segs, unsigned int to_read)
@@ -420,11 +438,7 @@ readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
 	struct msghdr smb_msg;
 	struct kvec *iov;
 
-	/*
-	 * FIXME: allocation here may cause deadlocks under memory pressure.
-	 * Switch this to use a fixed, per-socket buffer.
-	 */
-	iov = kmalloc(sizeof(*iov_orig) * nr_segs, GFP_KERNEL);
+	iov = get_server_iovec(server, nr_segs);
 	if (!iov)
 		return -ENOMEM;
 
@@ -468,7 +482,6 @@ readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
 			break;
 		}
 	}
-	kfree(iov);
 	return total_read;
 }
 
@@ -686,6 +699,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 	}
 
 	kfree(server->hostname);
+	kfree(server->iov);
 	kfree(server);
 
 	length = atomic_dec_return(&tcpSesAllocCount);
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 09/16] cifs: clean up check_rfc1002_header
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (7 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 08/16] cifs: keep a reusable kvec array for receives Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 10/16] cifs: add a third receive phase to cifs_demultiplex_thread Jeff Layton
                     ` (7 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Rename it for better clarity as to what it does and have the caller pass
in just the single type byte. Turn the if statement into a switch and
optimize it by placing the most common message type at the top. Move the
header length check back into cifs_demultiplex_thread in preparation
for adding a new receive phase and normalize the cFYI messages.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   63 +++++++++++++++++++++++++---------------------------
 1 files changed, 30 insertions(+), 33 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f7bd9ba..eb76b29 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -498,29 +498,29 @@ read_from_socket(struct TCP_Server_Info *server, char *buf,
 }
 
 static bool
-check_rfc1002_header(struct TCP_Server_Info *server, char *buf)
+is_smb_response(struct TCP_Server_Info *server, unsigned char type)
 {
-	char temp = *buf;
-	unsigned int pdu_length = be32_to_cpu(
-				((struct smb_hdr *)buf)->smb_buf_length);
-
 	/*
 	 * The first byte big endian of the length field,
 	 * is actually not part of the length but the type
 	 * with the most common, zero, as regular data.
 	 */
-	if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
-		return false;
-	} else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
-		cFYI(1, "Good RFC 1002 session rsp");
-		return false;
-	} else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+	switch (type) {
+	case RFC1002_SESSION_MESSAGE:
+		/* Regular SMB response */
+		return true;
+	case RFC1002_SESSION_KEEP_ALIVE:
+		cFYI(1, "RFC 1002 session keep alive");
+		break;
+	case RFC1002_POSITIVE_SESSION_RESPONSE:
+		cFYI(1, "RFC 1002 positive session response");
+		break;
+	case RFC1002_NEGATIVE_SESSION_RESPONSE:
 		/*
 		 * We get this from Windows 98 instead of an error on
 		 * SMB negprot response.
 		 */
-		cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
-			pdu_length);
+		cFYI(1, "RFC 1002 negative session response");
 		/* give server a second to clean up */
 		msleep(1000);
 		/*
@@ -529,29 +529,16 @@ check_rfc1002_header(struct TCP_Server_Info *server, char *buf)
 		 * is since we do not begin with RFC1001 session
 		 * initialize frame).
 		 */
-		cifs_set_port((struct sockaddr *)
-				&server->dstaddr, CIFS_PORT);
+		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
 		cifs_reconnect(server);
 		wake_up(&server->response_q);
-		return false;
-	} else if (temp != (char) 0) {
-		cERROR(1, "Unknown RFC 1002 frame");
-		cifs_dump_mem(" Received Data: ", buf, 4);
-		cifs_reconnect(server);
-		return false;
-	}
-
-	/* else we have an SMB response */
-	if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
-	    (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
-		cERROR(1, "Invalid size SMB length %d pdu_length %d",
-		       4, pdu_length+4);
+		break;
+	default:
+		cERROR(1, "RFC 1002 unknown response type 0x%x", type);
 		cifs_reconnect(server);
-		wake_up(&server->response_q);
-		return false;
 	}
 
-	return true;
+	return false;
 }
 
 static struct mid_q_entry *
@@ -755,10 +742,20 @@ cifs_demultiplex_thread(void *p)
 		 */
 		pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
 
-		cFYI(1, "rfc1002 length 0x%x", pdu_length+4);
-		if (!check_rfc1002_header(server, buf))
+		cFYI(1, "RFC1002 header 0x%x", pdu_length);
+		if (!is_smb_response(server, buf[0]))
 			continue;
 
+		/* check the length */
+		if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
+		    (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
+			cERROR(1, "Invalid size SMB length %d pdu_length %d",
+			       4, pdu_length + 4);
+			cifs_reconnect(server);
+			wake_up(&server->response_q);
+			continue;
+		}
+
 		/* else length ok */
 		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
 			isLargeBuf = true;
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 10/16] cifs: add a third receive phase to cifs_demultiplex_thread
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (8 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 09/16] cifs: clean up check_rfc1002_header Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 11/16] cifs: move mid finding into separate routine Jeff Layton
                     ` (6 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Have the demultiplex thread receive just enough to get to the MID, and
then find it before receiving the rest. Later, we'll use this to swap
in a preallocated receive buffer for some calls.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   31 ++++++++++++++++++++++++-------
 1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index eb76b29..af4c9eb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -746,11 +746,25 @@ cifs_demultiplex_thread(void *p)
 		if (!is_smb_response(server, buf[0]))
 			continue;
 
-		/* check the length */
-		if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
-		    (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
-			cERROR(1, "Invalid size SMB length %d pdu_length %d",
-			       4, pdu_length + 4);
+		/* make sure we have enough to get to the MID */
+		if (pdu_length < sizeof(struct smb_hdr) - 1 - 4) {
+			cERROR(1, "SMB response too short (%u bytes)",
+				pdu_length);
+			cifs_reconnect(server);
+			wake_up(&server->response_q);
+			continue;
+		}
+
+		/* read down to the MID */
+		length = read_from_socket(server, buf + 4,
+					  sizeof(struct smb_hdr) - 1 - 4);
+		if (length < 0)
+			continue;
+		total_read += length;
+
+		if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+			cERROR(1, "SMB response too long (%u bytes)",
+				pdu_length);
 			cifs_reconnect(server);
 			wake_up(&server->response_q);
 			continue;
@@ -759,12 +773,15 @@ cifs_demultiplex_thread(void *p)
 		/* else length ok */
 		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
 			isLargeBuf = true;
-			memcpy(bigbuf, smallbuf, 4);
+			memcpy(bigbuf, smallbuf, total_read);
 			smb_buffer = (struct smb_hdr *)bigbuf;
 			buf = bigbuf;
 		}
 
-		length = read_from_socket(server, buf + 4, pdu_length);
+		/* now read the rest */
+		length = read_from_socket(server,
+				  buf + sizeof(struct smb_hdr) - 1,
+				  pdu_length - sizeof(struct smb_hdr) + 1 + 4);
 		if (length < 0)
 			continue;
 		total_read += length;
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 11/16] cifs: move mid finding into separate routine
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (9 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 10/16] cifs: add a third receive phase to cifs_demultiplex_thread Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 12/16] cifs: eliminate is_multi_rsp parm to find_cifs_mid Jeff Layton
                     ` (5 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Begin breaking up find_cifs_mid into smaller pieces. The parts that
coalesce T2 responses don't really need to be done under the
GlobalMid_lock anyway. Create a new function that just finds the
mid on the list, and then later takes it off the list if the entire
response has been received.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |  113 +++++++++++++++++++++++++++++++----------------------
 1 files changed, 66 insertions(+), 47 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index af4c9eb..6d41859 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -542,61 +542,80 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
 }
 
 static struct mid_q_entry *
-find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
-	      int *length, bool is_large_buf, bool *is_multi_rsp, char **bigbuf)
+find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf)
 {
-	struct mid_q_entry *mid = NULL, *tmp_mid, *ret = NULL;
+	struct mid_q_entry *mid;
 
 	spin_lock(&GlobalMid_Lock);
-	list_for_each_entry_safe(mid, tmp_mid, &server->pending_mid_q, qhead) {
-		if (mid->mid != buf->Mid ||
-		    mid->midState != MID_REQUEST_SUBMITTED ||
-		    mid->command != buf->Command)
-			continue;
-
-		if (*length == 0 && check2ndT2(buf) > 0) {
-			/* We have a multipart transact2 resp */
-			*is_multi_rsp = true;
-			if (mid->resp_buf) {
-				/* merge response - fix up 1st*/
-				*length = coalesce_t2(buf, mid->resp_buf);
-				if (*length > 0) {
-					*length = 0;
-					mid->multiRsp = true;
-					break;
-				}
-				/* All parts received or packet is malformed. */
-				mid->multiEnd = true;
-				goto multi_t2_fnd;
-			}
-			if (!is_large_buf) {
-				/*FIXME: switch to already allocated largebuf?*/
-				cERROR(1, "1st trans2 resp needs bigbuf");
-			} else {
-				/* Have first buffer */
-				mid->resp_buf = buf;
-				mid->largeBuf = true;
-				*bigbuf = NULL;
-			}
-			break;
+	list_for_each_entry(mid, &server->pending_mid_q, qhead) {
+		if (mid->mid == buf->Mid &&
+		    mid->midState == MID_REQUEST_SUBMITTED &&
+		    mid->command == buf->Command) {
+			spin_unlock(&GlobalMid_Lock);
+			return mid;
 		}
-		mid->resp_buf = buf;
-		mid->largeBuf = is_large_buf;
-multi_t2_fnd:
-		if (*length == 0)
-			mid->midState = MID_RESPONSE_RECEIVED;
-		else
-			mid->midState = MID_RESPONSE_MALFORMED;
+	}
+	spin_unlock(&GlobalMid_Lock);
+	return NULL;
+}
+
+static void
+dequeue_mid(struct mid_q_entry *mid, int malformed)
+{
 #ifdef CONFIG_CIFS_STATS2
-		mid->when_received = jiffies;
+	mid->when_received = jiffies;
 #endif
-		list_del_init(&mid->qhead);
-		ret = mid;
-		break;
-	}
+	spin_lock(&GlobalMid_Lock);
+	if (!malformed)
+		mid->midState = MID_RESPONSE_RECEIVED;
+	else
+		mid->midState = MID_RESPONSE_MALFORMED;
+	list_del_init(&mid->qhead);
 	spin_unlock(&GlobalMid_Lock);
+}
 
-	return ret;
+static struct mid_q_entry *
+find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
+	      int *malformed, bool is_large_buf, bool *is_multi_rsp,
+	      char **bigbuf)
+{
+	struct mid_q_entry *mid = NULL;
+
+	mid = find_mid(server, buf);
+	if (!mid)
+		return mid;
+
+	if (*malformed == 0 && check2ndT2(buf) > 0) {
+		/* We have a multipart transact2 resp */
+		*is_multi_rsp = true;
+		if (mid->resp_buf) {
+			/* merge response - fix up 1st*/
+			*malformed = coalesce_t2(buf, mid->resp_buf);
+			if (*malformed > 0) {
+				*malformed = 0;
+				mid->multiRsp = true;
+				return NULL;
+			}
+			/* All parts received or packet is malformed. */
+			mid->multiEnd = true;
+			goto multi_t2_fnd;
+		}
+		if (!is_large_buf) {
+			/*FIXME: switch to already allocated largebuf?*/
+			cERROR(1, "1st trans2 resp needs bigbuf");
+		} else {
+			/* Have first buffer */
+			mid->resp_buf = buf;
+			mid->largeBuf = true;
+			*bigbuf = NULL;
+		}
+		return mid;
+	}
+	mid->resp_buf = buf;
+	mid->largeBuf = is_large_buf;
+multi_t2_fnd:
+	dequeue_mid(mid, *malformed);
+	return mid;
 }
 
 static void clean_demultiplex_info(struct TCP_Server_Info *server)
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 12/16] cifs: eliminate is_multi_rsp parm to find_cifs_mid
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (10 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 11/16] cifs: move mid finding into separate routine Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 13/16] cifs: move buffer pointers into TCP_Server_Info Jeff Layton
                     ` (4 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Change find_cifs_mid to only return NULL if a mid could not be found.
If we got part of a multi-part T2 response, then coalesce it and still
return the mid. The caller can determine the T2 receive status from
the flags in the mid.

With this change, there is no need to pass a pointer to "length" as
well and just pass by value. If a mid is found, then we can just mark
it as malformed. If one isn't found, then the value of "length" won't
change anyway.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   35 ++++++++++++++++-------------------
 1 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 6d41859..89950bd 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -576,8 +576,7 @@ dequeue_mid(struct mid_q_entry *mid, int malformed)
 
 static struct mid_q_entry *
 find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
-	      int *malformed, bool is_large_buf, bool *is_multi_rsp,
-	      char **bigbuf)
+	      int malformed, bool is_large_buf, char **bigbuf)
 {
 	struct mid_q_entry *mid = NULL;
 
@@ -585,16 +584,14 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
 	if (!mid)
 		return mid;
 
-	if (*malformed == 0 && check2ndT2(buf) > 0) {
-		/* We have a multipart transact2 resp */
-		*is_multi_rsp = true;
+	if (malformed == 0 && check2ndT2(buf) > 0) {
+		mid->multiRsp = true;
 		if (mid->resp_buf) {
 			/* merge response - fix up 1st*/
-			*malformed = coalesce_t2(buf, mid->resp_buf);
-			if (*malformed > 0) {
-				*malformed = 0;
-				mid->multiRsp = true;
-				return NULL;
+			malformed = coalesce_t2(buf, mid->resp_buf);
+			if (malformed > 0) {
+				malformed = 0;
+				return mid;
 			}
 			/* All parts received or packet is malformed. */
 			mid->multiEnd = true;
@@ -614,7 +611,7 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
 	mid->resp_buf = buf;
 	mid->largeBuf = is_large_buf;
 multi_t2_fnd:
-	dequeue_mid(mid, *malformed);
+	dequeue_mid(mid, malformed);
 	return mid;
 }
 
@@ -725,7 +722,6 @@ cifs_demultiplex_thread(void *p)
 	struct task_struct *task_to_wake = NULL;
 	struct mid_q_entry *mid_entry;
 	bool isLargeBuf = false;
-	bool isMultiRsp = false;
 
 	current->flags |= PF_MEMALLOC;
 	cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
@@ -745,7 +741,6 @@ cifs_demultiplex_thread(void *p)
 			continue;
 
 		isLargeBuf = false;
-		isMultiRsp = false;
 		smb_buffer = (struct smb_hdr *)smallbuf;
 		buf = smallbuf;
 		pdu_length = 4; /* enough to get RFC1001 header */
@@ -823,23 +818,25 @@ cifs_demultiplex_thread(void *p)
 
 		server->lstrp = jiffies;
 
-		mid_entry = find_cifs_mid(server, smb_buffer, &length,
-					  isLargeBuf, &isMultiRsp, &bigbuf);
+		mid_entry = find_cifs_mid(server, smb_buffer, length,
+					  isLargeBuf, &bigbuf);
 		if (mid_entry != NULL) {
-			mid_entry->callback(mid_entry);
+			if (mid_entry->multiRsp && !mid_entry->multiEnd)
+				continue;
+
 			/* Was previous buf put in mpx struct for multi-rsp? */
-			if (!isMultiRsp) {
+			if (!mid_entry->multiRsp) {
 				/* smb buffer will be freed by user thread */
 				if (isLargeBuf)
 					bigbuf = NULL;
 				else
 					smallbuf = NULL;
 			}
+			mid_entry->callback(mid_entry);
 		} else if (length != 0) {
 			/* response sanity checks failed */
 			continue;
-		} else if (!is_valid_oplock_break(smb_buffer, server) &&
-			   !isMultiRsp) {
+		} else if (!is_valid_oplock_break(smb_buffer, server)) {
 			cERROR(1, "No task to wake, unknown frame received! "
 				   "NumMids %d", atomic_read(&midCount));
 			cifs_dump_mem("Received Data is: ", buf,
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 13/16] cifs: move buffer pointers into TCP_Server_Info
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (11 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 12/16] cifs: eliminate is_multi_rsp parm to find_cifs_mid Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 14/16] cifs: find mid earlier in receive codepath Jeff Layton
                     ` (3 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

We have several functions that need to access these pointers. Currently
that's done with a lot of double pointer passing. Instead, move them
into the TCP_Server_Info and simplify the handling.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsglob.h |    4 ++
 fs/cifs/connect.c  |  101 +++++++++++++++++++++++----------------------------
 2 files changed, 50 insertions(+), 55 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7d93c62..efa8b37 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -286,9 +286,13 @@ struct TCP_Server_Info {
 	bool	sec_kerberosu2u;	/* supports U2U Kerberos */
 	bool	sec_kerberos;		/* supports plain Kerberos */
 	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
+	bool	large_buf;		/* is current buffer large? */
 	struct delayed_work	echo; /* echo ping workqueue job */
 	struct kvec *iov;	/* reusable kvec array for receives */
 	unsigned int nr_iov;	/* number of kvecs in array */
+	char	*smallbuf;	/* pointer to current "small" buffer */
+	char	*bigbuf;	/* pointer to current "big" buffer */
+	unsigned int total_read; /* total amount of data read in this pass */
 #ifdef CONFIG_CIFS_FSCACHE
 	struct fscache_cookie   *fscache; /* client index cache cookie */
 #endif
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 89950bd..5c0898a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -320,27 +320,24 @@ requeue_echo:
 }
 
 static bool
-allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
-		 bool is_large_buf)
+allocate_buffers(struct TCP_Server_Info *server)
 {
-	char *bbuf = *bigbuf, *sbuf = *smallbuf;
-
-	if (bbuf == NULL) {
-		bbuf = (char *)cifs_buf_get();
-		if (!bbuf) {
+	if (!server->bigbuf) {
+		server->bigbuf = (char *)cifs_buf_get();
+		if (!server->bigbuf) {
 			cERROR(1, "No memory for large SMB response");
 			msleep(3000);
 			/* retry will check if exiting */
 			return false;
 		}
-	} else if (is_large_buf) {
+	} else if (server->large_buf) {
 		/* we are reusing a dirty large buf, clear its start */
-		memset(bbuf, 0, size);
+		memset(server->bigbuf, 0, sizeof(struct smb_hdr));
 	}
 
-	if (sbuf == NULL) {
-		sbuf = (char *)cifs_small_buf_get();
-		if (!sbuf) {
+	if (!server->smallbuf) {
+		server->smallbuf = (char *)cifs_small_buf_get();
+		if (!server->smallbuf) {
 			cERROR(1, "No memory for SMB response");
 			msleep(1000);
 			/* retry will check if exiting */
@@ -349,12 +346,9 @@ allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
 		/* beginning of smb buffer is cleared in our buf_get */
 	} else {
 		/* if existing small buf clear beginning */
-		memset(sbuf, 0, size);
+		memset(server->smallbuf, 0, sizeof(struct smb_hdr));
 	}
 
-	*bigbuf = bbuf;
-	*smallbuf = sbuf;
-
 	return true;
 }
 
@@ -576,7 +570,7 @@ dequeue_mid(struct mid_q_entry *mid, int malformed)
 
 static struct mid_q_entry *
 find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
-	      int malformed, bool is_large_buf, char **bigbuf)
+	      int malformed)
 {
 	struct mid_q_entry *mid = NULL;
 
@@ -597,19 +591,27 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
 			mid->multiEnd = true;
 			goto multi_t2_fnd;
 		}
-		if (!is_large_buf) {
+		if (!server->large_buf) {
 			/*FIXME: switch to already allocated largebuf?*/
 			cERROR(1, "1st trans2 resp needs bigbuf");
 		} else {
 			/* Have first buffer */
 			mid->resp_buf = buf;
 			mid->largeBuf = true;
-			*bigbuf = NULL;
+			server->bigbuf = NULL;
 		}
 		return mid;
 	}
 	mid->resp_buf = buf;
-	mid->largeBuf = is_large_buf;
+	mid->largeBuf = server->large_buf;
+	/* Was previous buf put in mpx struct for multi-rsp? */
+	if (!mid->multiRsp) {
+		/* smb buffer will be freed by user thread */
+		if (server->large_buf)
+			server->bigbuf = NULL;
+		else
+			server->smallbuf = NULL;
+	}
 multi_t2_fnd:
 	dequeue_mid(mid, malformed);
 	return mid;
@@ -716,12 +718,11 @@ cifs_demultiplex_thread(void *p)
 {
 	int length;
 	struct TCP_Server_Info *server = p;
-	unsigned int pdu_length, total_read;
-	char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
+	unsigned int pdu_length;
+	char *buf = NULL;
 	struct smb_hdr *smb_buffer = NULL;
 	struct task_struct *task_to_wake = NULL;
 	struct mid_q_entry *mid_entry;
-	bool isLargeBuf = false;
 
 	current->flags |= PF_MEMALLOC;
 	cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
@@ -736,19 +737,18 @@ cifs_demultiplex_thread(void *p)
 		if (try_to_freeze())
 			continue;
 
-		if (!allocate_buffers(&bigbuf, &smallbuf,
-				      sizeof(struct smb_hdr), isLargeBuf))
+		if (!allocate_buffers(server))
 			continue;
 
-		isLargeBuf = false;
-		smb_buffer = (struct smb_hdr *)smallbuf;
-		buf = smallbuf;
+		server->large_buf = false;
+		smb_buffer = (struct smb_hdr *)server->smallbuf;
+		buf = server->smallbuf;
 		pdu_length = 4; /* enough to get RFC1001 header */
 
 		length = read_from_socket(server, buf, pdu_length);
 		if (length < 0)
 			continue;
-		total_read = length;
+		server->total_read = length;
 
 		/*
 		 * The right amount was read from socket - 4 bytes,
@@ -774,7 +774,7 @@ cifs_demultiplex_thread(void *p)
 					  sizeof(struct smb_hdr) - 1 - 4);
 		if (length < 0)
 			continue;
-		total_read += length;
+		server->total_read += length;
 
 		if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 			cERROR(1, "SMB response too long (%u bytes)",
@@ -786,10 +786,11 @@ cifs_demultiplex_thread(void *p)
 
 		/* else length ok */
 		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
-			isLargeBuf = true;
-			memcpy(bigbuf, smallbuf, total_read);
-			smb_buffer = (struct smb_hdr *)bigbuf;
-			buf = bigbuf;
+			server->large_buf = true;
+			memcpy(server->bigbuf, server->smallbuf,
+			       server->total_read);
+			smb_buffer = (struct smb_hdr *)server->bigbuf;
+			buf = server->bigbuf;
 		}
 
 		/* now read the rest */
@@ -798,9 +799,9 @@ cifs_demultiplex_thread(void *p)
 				  pdu_length - sizeof(struct smb_hdr) + 1 + 4);
 		if (length < 0)
 			continue;
-		total_read += length;
+		server->total_read += length;
 
-		dump_smb(smb_buffer, total_read);
+		dump_smb(smb_buffer, server->total_read);
 
 		/*
 		 * We know that we received enough to get to the MID as we
@@ -811,28 +812,18 @@ cifs_demultiplex_thread(void *p)
 		 * 48 bytes is enough to display the header and a little bit
 		 * into the payload for debugging purposes.
 		 */
-		length = checkSMB(smb_buffer, smb_buffer->Mid, total_read);
+		length = checkSMB(smb_buffer, smb_buffer->Mid,
+				  server->total_read);
 		if (length != 0)
 			cifs_dump_mem("Bad SMB: ", buf,
-				      min_t(unsigned int, total_read, 48));
+				min_t(unsigned int, server->total_read, 48));
 
 		server->lstrp = jiffies;
 
-		mid_entry = find_cifs_mid(server, smb_buffer, length,
-					  isLargeBuf, &bigbuf);
+		mid_entry = find_cifs_mid(server, smb_buffer, length);
 		if (mid_entry != NULL) {
-			if (mid_entry->multiRsp && !mid_entry->multiEnd)
-				continue;
-
-			/* Was previous buf put in mpx struct for multi-rsp? */
-			if (!mid_entry->multiRsp) {
-				/* smb buffer will be freed by user thread */
-				if (isLargeBuf)
-					bigbuf = NULL;
-				else
-					smallbuf = NULL;
-			}
-			mid_entry->callback(mid_entry);
+			if (!mid_entry->multiRsp || mid_entry->multiEnd)
+				mid_entry->callback(mid_entry);
 		} else if (length != 0) {
 			/* response sanity checks failed */
 			continue;
@@ -850,9 +841,9 @@ cifs_demultiplex_thread(void *p)
 	} /* end while !EXITING */
 
 	/* buffer usually freed in free_mid - need to free it here on exit */
-	cifs_buf_release(bigbuf);
-	if (smallbuf) /* no sense logging a debug message if NULL */
-		cifs_small_buf_release(smallbuf);
+	cifs_buf_release(server->bigbuf);
+	if (server->smallbuf) /* no sense logging a debug message if NULL */
+		cifs_small_buf_release(server->smallbuf);
 
 	task_to_wake = xchg(&server->tsk, NULL);
 	clean_demultiplex_info(server);
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 14/16] cifs: find mid earlier in receive codepath
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (12 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 13/16] cifs: move buffer pointers into TCP_Server_Info Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 15/16] cifs: break out 3rd receive phase into separate function Jeff Layton
                     ` (2 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

In order to receive directly into a preallocated buffer, we need to ID
the mid earlier, before the bulk of the response is read. Call the mid
finding routine as soon as we're able to read the mid.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   24 +++++++++---------------
 1 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5c0898a..8a43619 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -568,16 +568,10 @@ dequeue_mid(struct mid_q_entry *mid, int malformed)
 	spin_unlock(&GlobalMid_Lock);
 }
 
-static struct mid_q_entry *
-find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
-	      int malformed)
+static void
+handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+	   struct smb_hdr *buf, int malformed)
 {
-	struct mid_q_entry *mid = NULL;
-
-	mid = find_mid(server, buf);
-	if (!mid)
-		return mid;
-
 	if (malformed == 0 && check2ndT2(buf) > 0) {
 		mid->multiRsp = true;
 		if (mid->resp_buf) {
@@ -585,11 +579,11 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
 			malformed = coalesce_t2(buf, mid->resp_buf);
 			if (malformed > 0) {
 				malformed = 0;
-				return mid;
+				return;
 			}
 			/* All parts received or packet is malformed. */
 			mid->multiEnd = true;
-			goto multi_t2_fnd;
+			return dequeue_mid(mid, malformed);
 		}
 		if (!server->large_buf) {
 			/*FIXME: switch to already allocated largebuf?*/
@@ -600,7 +594,7 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
 			mid->largeBuf = true;
 			server->bigbuf = NULL;
 		}
-		return mid;
+		return;
 	}
 	mid->resp_buf = buf;
 	mid->largeBuf = server->large_buf;
@@ -612,9 +606,7 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
 		else
 			server->smallbuf = NULL;
 	}
-multi_t2_fnd:
 	dequeue_mid(mid, malformed);
-	return mid;
 }
 
 static void clean_demultiplex_info(struct TCP_Server_Info *server)
@@ -776,6 +768,8 @@ cifs_demultiplex_thread(void *p)
 			continue;
 		server->total_read += length;
 
+		mid_entry = find_mid(server, smb_buffer);
+
 		if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 			cERROR(1, "SMB response too long (%u bytes)",
 				pdu_length);
@@ -820,8 +814,8 @@ cifs_demultiplex_thread(void *p)
 
 		server->lstrp = jiffies;
 
-		mid_entry = find_cifs_mid(server, smb_buffer, length);
 		if (mid_entry != NULL) {
+			handle_mid(mid_entry, server, smb_buffer, length);
 			if (!mid_entry->multiRsp || mid_entry->multiEnd)
 				mid_entry->callback(mid_entry);
 		} else if (length != 0) {
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 15/16] cifs: break out 3rd receive phase into separate function
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (13 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 14/16] cifs: find mid earlier in receive codepath Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-26 19:06   ` [PATCH 16/16] cifs: add a callback function to receive the rest of the frame Jeff Layton
  2011-08-27 18:47   ` [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2) Pavel Shilovsky
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Move the entire 3rd phase of the receive codepath into a separate
function in preparation for the addition of a pluggable receive
function.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |  101 +++++++++++++++++++++++++++++++----------------------
 1 files changed, 59 insertions(+), 42 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8a43619..dd4c3bae 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -706,6 +706,61 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 }
 
 static int
+standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+	int length;
+	char *buf = server->smallbuf;
+	struct smb_hdr *smb_buffer = (struct smb_hdr *)buf;
+	unsigned int pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
+
+	/* make sure this will fit in a large buffer */
+	if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		cERROR(1, "SMB response too long (%u bytes)",
+			pdu_length);
+		cifs_reconnect(server);
+		wake_up(&server->response_q);
+		return -EAGAIN;
+	}
+
+	/* switch to large buffer if too big for a small one */
+	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
+		server->large_buf = true;
+		memcpy(server->bigbuf, server->smallbuf, server->total_read);
+		buf = server->bigbuf;
+		smb_buffer = (struct smb_hdr *)buf;
+	}
+
+	/* now read the rest */
+	length = read_from_socket(server,
+			  buf + sizeof(struct smb_hdr) - 1,
+			  pdu_length - sizeof(struct smb_hdr) + 1 + 4);
+	if (length < 0)
+		return length;
+	server->total_read += length;
+
+	dump_smb(smb_buffer, server->total_read);
+
+	/*
+	 * We know that we received enough to get to the MID as we
+	 * checked the pdu_length earlier. Now check to see
+	 * if the rest of the header is OK. We borrow the length
+	 * var for the rest of the loop to avoid a new stack var.
+	 *
+	 * 48 bytes is enough to display the header and a little bit
+	 * into the payload for debugging purposes.
+	 */
+	length = checkSMB(smb_buffer, smb_buffer->Mid, server->total_read);
+	if (length != 0)
+		cifs_dump_mem("Bad SMB: ", buf,
+			min_t(unsigned int, server->total_read, 48));
+
+	if (mid)
+		handle_mid(mid, server, smb_buffer, length);
+
+	return length;
+}
+
+static int
 cifs_demultiplex_thread(void *p)
 {
 	int length;
@@ -770,57 +825,19 @@ cifs_demultiplex_thread(void *p)
 
 		mid_entry = find_mid(server, smb_buffer);
 
-		if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-			cERROR(1, "SMB response too long (%u bytes)",
-				pdu_length);
-			cifs_reconnect(server);
-			wake_up(&server->response_q);
+		length = standard_receive3(server, mid_entry);
+		if (length < 0)
 			continue;
-		}
 
-		/* else length ok */
-		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
-			server->large_buf = true;
-			memcpy(server->bigbuf, server->smallbuf,
-			       server->total_read);
-			smb_buffer = (struct smb_hdr *)server->bigbuf;
+		if (server->large_buf) {
 			buf = server->bigbuf;
+			smb_buffer = (struct smb_hdr *)buf;
 		}
 
-		/* now read the rest */
-		length = read_from_socket(server,
-				  buf + sizeof(struct smb_hdr) - 1,
-				  pdu_length - sizeof(struct smb_hdr) + 1 + 4);
-		if (length < 0)
-			continue;
-		server->total_read += length;
-
-		dump_smb(smb_buffer, server->total_read);
-
-		/*
-		 * We know that we received enough to get to the MID as we
-		 * checked the pdu_length earlier. Now check to see
-		 * if the rest of the header is OK. We borrow the length
-		 * var for the rest of the loop to avoid a new stack var.
-		 *
-		 * 48 bytes is enough to display the header and a little bit
-		 * into the payload for debugging purposes.
-		 */
-		length = checkSMB(smb_buffer, smb_buffer->Mid,
-				  server->total_read);
-		if (length != 0)
-			cifs_dump_mem("Bad SMB: ", buf,
-				min_t(unsigned int, server->total_read, 48));
-
 		server->lstrp = jiffies;
-
 		if (mid_entry != NULL) {
-			handle_mid(mid_entry, server, smb_buffer, length);
 			if (!mid_entry->multiRsp || mid_entry->multiEnd)
 				mid_entry->callback(mid_entry);
-		} else if (length != 0) {
-			/* response sanity checks failed */
-			continue;
 		} else if (!is_valid_oplock_break(smb_buffer, server)) {
 			cERROR(1, "No task to wake, unknown frame received! "
 				   "NumMids %d", atomic_read(&midCount));
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 16/16] cifs: add a callback function to receive the rest of the frame
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (14 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 15/16] cifs: break out 3rd receive phase into separate function Jeff Layton
@ 2011-08-26 19:06   ` Jeff Layton
  2011-08-27 18:47   ` [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2) Pavel Shilovsky
  16 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-26 19:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

In order to handle larger SMBs for readpages and other calls, we want
to be able to read into a preallocated set of buffers. Rather than
changing all of the existing code to preallocate buffers however, we
instead add a receive callback function to the MID.

cifsd will call this function once the mid_q_entry has been identified
in order to receive the rest of the SMB. If the mid can't be identified
or the receive pointer is unset, then the standard 3rd phase receive
function will be called.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsglob.h  |   23 ++++++++++++++++++++---
 fs/cifs/cifsproto.h |    5 +++--
 fs/cifs/cifssmb.c   |    5 +++--
 fs/cifs/connect.c   |    6 +++++-
 fs/cifs/transport.c |    5 +++--
 5 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index efa8b37..214fe47 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -649,8 +649,24 @@ static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
 struct mid_q_entry;
 
 /*
- * This is the prototype for the mid callback function. When creating one,
- * take special care to avoid deadlocks. Things to bear in mind:
+ * This is the prototype for the mid receive function. This function is for
+ * receiving the rest of the SMB frame, starting with the WordCount (which is
+ * just after the MID in struct smb_hdr). Note:
+ *
+ * - This will be called by cifsd, with no locks held.
+ * - The mid will still be on the pending_mid_q.
+ * - mid->resp_buf will point to the current buffer.
+ *
+ * Returns zero on a successful receive, or an error. The receive state in
+ * the TCP_Server_Info will also be updated.
+ */
+typedef int (mid_receive_t)(struct TCP_Server_Info *server,
+			    struct mid_q_entry *mid);
+
+/*
+ * This is the prototype for the mid callback function. This is called once the
+ * mid has been received off of the socket. When creating one, take special
+ * care to avoid deadlocks. Things to bear in mind:
  *
  * - it will be called by cifsd, with no locks held
  * - the mid will be removed from any lists
@@ -668,9 +684,10 @@ struct mid_q_entry {
 	unsigned long when_sent; /* time when smb send finished */
 	unsigned long when_received; /* when demux complete (taken off wire) */
 #endif
+	mid_receive_t *receive; /* call receive callback */
 	mid_callback_t *callback; /* call completion callback */
 	void *callback_data;	  /* general purpose pointer for callback */
-	struct smb_hdr *resp_buf;	/* response buffer */
+	struct smb_hdr *resp_buf;	/* pointer to received SMB header */
 	int midState;	/* wish this were enum but can not pass to wait_event */
 	__u8 command;	/* smb command code */
 	bool largeBuf:1;	/* if valid response, is pointer to large buf */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 03dc945..51c0ebc 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -69,8 +69,9 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
 					struct TCP_Server_Info *server);
 extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
 extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
-			   unsigned int nvec, mid_callback_t *callback,
-			   void *cbdata, bool ignore_pend);
+			   unsigned int nvec, mid_receive_t *receive,
+			   mid_callback_t *callback, void *cbdata,
+			   bool ignore_pend);
 extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
 			struct smb_hdr * /* input */ ,
 			struct smb_hdr * /* out */ ,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 52fc500..911bc7e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -748,7 +748,8 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
 	iov.iov_base = smb;
 	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
 
-	rc = cifs_call_async(server, &iov, 1, cifs_echo_callback, server, true);
+	rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
+			     server, true);
 	if (rc)
 		cFYI(1, "Echo request failed: %d", rc);
 
@@ -1845,7 +1846,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
 
 	kref_get(&wdata->refcount);
 	rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
-			     cifs_writev_callback, wdata, false);
+			     NULL, cifs_writev_callback, wdata, false);
 
 	if (rc == 0)
 		cifs_stats_inc(&tcon->num_writes);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index dd4c3bae..9d0b1c2 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -825,7 +825,11 @@ cifs_demultiplex_thread(void *p)
 
 		mid_entry = find_mid(server, smb_buffer);
 
-		length = standard_receive3(server, mid_entry);
+		if (!mid_entry || !mid_entry->receive)
+			length = standard_receive3(server, mid_entry);
+		else
+			length = mid_entry->receive(server, mid_entry);
+
 		if (length < 0)
 			continue;
 
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 316d4cb..cbad728 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -343,8 +343,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
  */
 int
 cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
-		unsigned int nvec, mid_callback_t *callback, void *cbdata,
-		bool ignore_pend)
+		unsigned int nvec, mid_receive_t *receive,
+		mid_callback_t *callback, void *cbdata, bool ignore_pend)
 {
 	int rc;
 	struct mid_q_entry *mid;
@@ -378,6 +378,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
 		goto out_err;
 	}
 
+	mid->receive = receive;
 	mid->callback = callback;
 	mid->callback_data = cbdata;
 	mid->midState = MID_REQUEST_SUBMITTED;
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
       [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (15 preceding siblings ...)
  2011-08-26 19:06   ` [PATCH 16/16] cifs: add a callback function to receive the rest of the frame Jeff Layton
@ 2011-08-27 18:47   ` Pavel Shilovsky
       [not found]     ` <CAKywueRCK+sw=GHBVn-mWe_Z1aWCH6uW=e=5MX7NNPY8Kum9tw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  16 siblings, 1 reply; 24+ messages in thread
From: Pavel Shilovsky @ 2011-08-27 18:47 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2011/8/26 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> This patchset does a fairly major cleanup and overhaul of the receive
> codepath for cifs. Aside from basic cleanup, there are two main goals:
>
> 1) allow the receive codepath to identify the mid before receiving all
> of the data for a particular SMB.
>
> ...and in turn...
>
> 2) add the ability for certain calls to receive their responses into
> their into their own set of buffers.
>
> These two changes allow cifs to break the CIFSMaxBufSize barrier for
> receives. This patchset just adds the necessary infrastructure to do
> the above.
>
> A separate patchset will follow that will overhaul cifs_readpages to use
> this infrastructure to allow for a larger rsize.
>
> Jeff Layton (16):
>  cifs: clean up checkSMB
>  cifs: consolidate signature generating code
>  cifs: trivial: remove obsolete comment
>  cifs: make smb_msg local to read_from_socket
>  cifs: check for unresponsive server every time we call kernel_recvmsg
>  cifs: simplify read_from_socket
>  cifs: turn read_from_socket into a wrapper around a vectorized
>    version
>  cifs: keep a reusable kvec array for receives
>  cifs: clean up check_rfc1002_header
>  cifs: add a third receive phase to cifs_demultiplex_thread
>  cifs: move mid finding into separate routine
>  cifs: eliminate is_multi_rsp parm to find_cifs_mid
>  cifs: move buffer pointers into TCP_Server_Info
>  cifs: find mid earlier in receive codepath
>  cifs: break out 3rd receive phase into separate function
>  cifs: add a callback function to receive the rest of the frame
>
>  fs/cifs/cifsencrypt.c |  103 ++--------
>  fs/cifs/cifsglob.h    |   29 +++-
>  fs/cifs/cifsproto.h   |    7 +-
>  fs/cifs/cifssmb.c     |    5 +-
>  fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
>  fs/cifs/misc.c        |   51 +++---
>  fs/cifs/transport.c   |   16 +-
>  7 files changed, 391 insertions(+), 339 deletions(-)
>
> --
> 1.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

The patchset looks good to me at the first glance. I am going to look
at this more carefully and test it in a few days.

-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
       [not found]     ` <CAKywueRCK+sw=GHBVn-mWe_Z1aWCH6uW=e=5MX7NNPY8Kum9tw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-10-04  9:04       ` Pavel Shilovsky
       [not found]         ` <CAKywueSboCYDxOF2a=Q0eLsKwWuai6BU5mnzAt_C_vjFkhSufw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Pavel Shilovsky @ 2011-10-04  9:04 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2011/8/27 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> 2011/8/26 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>> This patchset does a fairly major cleanup and overhaul of the receive
>> codepath for cifs. Aside from basic cleanup, there are two main goals:
>>
>> 1) allow the receive codepath to identify the mid before receiving all
>> of the data for a particular SMB.
>>
>> ...and in turn...
>>
>> 2) add the ability for certain calls to receive their responses into
>> their into their own set of buffers.
>>
>> These two changes allow cifs to break the CIFSMaxBufSize barrier for
>> receives. This patchset just adds the necessary infrastructure to do
>> the above.
>>
>> A separate patchset will follow that will overhaul cifs_readpages to use
>> this infrastructure to allow for a larger rsize.
>>
>> Jeff Layton (16):
>>  cifs: clean up checkSMB
>>  cifs: consolidate signature generating code
>>  cifs: trivial: remove obsolete comment
>>  cifs: make smb_msg local to read_from_socket
>>  cifs: check for unresponsive server every time we call kernel_recvmsg
>>  cifs: simplify read_from_socket
>>  cifs: turn read_from_socket into a wrapper around a vectorized
>>    version
>>  cifs: keep a reusable kvec array for receives
>>  cifs: clean up check_rfc1002_header
>>  cifs: add a third receive phase to cifs_demultiplex_thread
>>  cifs: move mid finding into separate routine
>>  cifs: eliminate is_multi_rsp parm to find_cifs_mid
>>  cifs: move buffer pointers into TCP_Server_Info
>>  cifs: find mid earlier in receive codepath
>>  cifs: break out 3rd receive phase into separate function
>>  cifs: add a callback function to receive the rest of the frame
>>
>>  fs/cifs/cifsencrypt.c |  103 ++--------
>>  fs/cifs/cifsglob.h    |   29 +++-
>>  fs/cifs/cifsproto.h   |    7 +-
>>  fs/cifs/cifssmb.c     |    5 +-
>>  fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
>>  fs/cifs/misc.c        |   51 +++---
>>  fs/cifs/transport.c   |   16 +-
>>  7 files changed, 391 insertions(+), 339 deletions(-)
>>
>> --
>> 1.7.6
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
> The patchset looks good to me at the first glance. I am going to look
> at this more carefully and test it in a few days.
>
> --
> Best regards,
> Pavel Shilovsky.
>

Sorry for the long delay on this. As patchwork.kernel.org isn't
available now, can you point me to public git repo, where I can fetch
that changes, please?

-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
       [not found]         ` <CAKywueSboCYDxOF2a=Q0eLsKwWuai6BU5mnzAt_C_vjFkhSufw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-10-04 11:00           ` Jeff Layton
       [not found]             ` <20111004070058.7d3cf2bf-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Jeff Layton @ 2011-10-04 11:00 UTC (permalink / raw)
  To: Pavel Shilovsky
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Tue, 4 Oct 2011 13:04:19 +0400
Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

> 2011/8/27 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> > 2011/8/26 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> >> This patchset does a fairly major cleanup and overhaul of the receive
> >> codepath for cifs. Aside from basic cleanup, there are two main goals:
> >>
> >> 1) allow the receive codepath to identify the mid before receiving all
> >> of the data for a particular SMB.
> >>
> >> ...and in turn...
> >>
> >> 2) add the ability for certain calls to receive their responses into
> >> their into their own set of buffers.
> >>
> >> These two changes allow cifs to break the CIFSMaxBufSize barrier for
> >> receives. This patchset just adds the necessary infrastructure to do
> >> the above.
> >>
> >> A separate patchset will follow that will overhaul cifs_readpages to use
> >> this infrastructure to allow for a larger rsize.
> >>
> >> Jeff Layton (16):
> >>  cifs: clean up checkSMB
> >>  cifs: consolidate signature generating code
> >>  cifs: trivial: remove obsolete comment
> >>  cifs: make smb_msg local to read_from_socket
> >>  cifs: check for unresponsive server every time we call kernel_recvmsg
> >>  cifs: simplify read_from_socket
> >>  cifs: turn read_from_socket into a wrapper around a vectorized
> >>    version
> >>  cifs: keep a reusable kvec array for receives
> >>  cifs: clean up check_rfc1002_header
> >>  cifs: add a third receive phase to cifs_demultiplex_thread
> >>  cifs: move mid finding into separate routine
> >>  cifs: eliminate is_multi_rsp parm to find_cifs_mid
> >>  cifs: move buffer pointers into TCP_Server_Info
> >>  cifs: find mid earlier in receive codepath
> >>  cifs: break out 3rd receive phase into separate function
> >>  cifs: add a callback function to receive the rest of the frame
> >>
> >>  fs/cifs/cifsencrypt.c |  103 ++--------
> >>  fs/cifs/cifsglob.h    |   29 +++-
> >>  fs/cifs/cifsproto.h   |    7 +-
> >>  fs/cifs/cifssmb.c     |    5 +-
> >>  fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
> >>  fs/cifs/misc.c        |   51 +++---
> >>  fs/cifs/transport.c   |   16 +-
> >>  7 files changed, 391 insertions(+), 339 deletions(-)
> >>
> >> --
> >> 1.7.6
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> >> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> >
> > The patchset looks good to me at the first glance. I am going to look
> > at this more carefully and test it in a few days.
> >
> > --
> > Best regards,
> > Pavel Shilovsky.
> >
> 
> Sorry for the long delay on this. As patchwork.kernel.org isn't
> available now, can you point me to public git repo, where I can fetch
> that changes, please?
> 


Yes, I've moved my git repo to samba.org for the time being:

http://git.samba.org/?p=jlayton/linux.git;a=summary

See the "cifs-3.2" branch.

-- 
Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
       [not found]             ` <20111004070058.7d3cf2bf-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
@ 2011-10-11 10:09               ` Pavel Shilovsky
       [not found]                 ` <CAKywueTByfFjDkMP8x5A8EJktqfKitbdipofujqJCwC5MknEuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Pavel Shilovsky @ 2011-10-11 10:09 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2011/10/4 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On Tue, 4 Oct 2011 13:04:19 +0400
> Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>> 2011/8/27 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
>> > 2011/8/26 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>> >> This patchset does a fairly major cleanup and overhaul of the receive
>> >> codepath for cifs. Aside from basic cleanup, there are two main goals:
>> >>
>> >> 1) allow the receive codepath to identify the mid before receiving all
>> >> of the data for a particular SMB.
>> >>
>> >> ...and in turn...
>> >>
>> >> 2) add the ability for certain calls to receive their responses into
>> >> their into their own set of buffers.
>> >>
>> >> These two changes allow cifs to break the CIFSMaxBufSize barrier for
>> >> receives. This patchset just adds the necessary infrastructure to do
>> >> the above.
>> >>
>> >> A separate patchset will follow that will overhaul cifs_readpages to use
>> >> this infrastructure to allow for a larger rsize.
>> >>
>> >> Jeff Layton (16):
>> >>  cifs: clean up checkSMB
>> >>  cifs: consolidate signature generating code
>> >>  cifs: trivial: remove obsolete comment
>> >>  cifs: make smb_msg local to read_from_socket
>> >>  cifs: check for unresponsive server every time we call kernel_recvmsg
>> >>  cifs: simplify read_from_socket
>> >>  cifs: turn read_from_socket into a wrapper around a vectorized
>> >>    version
>> >>  cifs: keep a reusable kvec array for receives
>> >>  cifs: clean up check_rfc1002_header
>> >>  cifs: add a third receive phase to cifs_demultiplex_thread
>> >>  cifs: move mid finding into separate routine
>> >>  cifs: eliminate is_multi_rsp parm to find_cifs_mid
>> >>  cifs: move buffer pointers into TCP_Server_Info
>> >>  cifs: find mid earlier in receive codepath
>> >>  cifs: break out 3rd receive phase into separate function
>> >>  cifs: add a callback function to receive the rest of the frame
>> >>
>> >>  fs/cifs/cifsencrypt.c |  103 ++--------
>> >>  fs/cifs/cifsglob.h    |   29 +++-
>> >>  fs/cifs/cifsproto.h   |    7 +-
>> >>  fs/cifs/cifssmb.c     |    5 +-
>> >>  fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
>> >>  fs/cifs/misc.c        |   51 +++---
>> >>  fs/cifs/transport.c   |   16 +-
>> >>  7 files changed, 391 insertions(+), 339 deletions(-)
>> >>
>> >> --
>> >> 1.7.6
>> >>
>> >> --
>> >> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
>> >> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >>
>> >
>> > The patchset looks good to me at the first glance. I am going to look
>> > at this more carefully and test it in a few days.
>> >
>> > --
>> > Best regards,
>> > Pavel Shilovsky.
>> >
>>
>> Sorry for the long delay on this. As patchwork.kernel.org isn't
>> available now, can you point me to public git repo, where I can fetch
>> that changes, please?
>>
>
>
> Yes, I've moved my git repo to samba.org for the time being:
>
> http://git.samba.org/?p=jlayton/linux.git;a=summary
>
> See the "cifs-3.2" branch.
>
> --
> Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>

I successfully tested this - the performance was closed to write one
in my case - about 11.5 MB on 100Mbit LAN against Windows 7 server.
Seems like a very good work!

-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
       [not found]                 ` <CAKywueTByfFjDkMP8x5A8EJktqfKitbdipofujqJCwC5MknEuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-10-11 10:16                   ` Pavel Shilovsky
       [not found]                     ` <CAKywueT3irL0zebNrxa_ErPLbT6NMgELos9e6dTe-0iPM4gz6A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Pavel Shilovsky @ 2011-10-11 10:16 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2011/10/11 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> 2011/10/4 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>> On Tue, 4 Oct 2011 13:04:19 +0400
>> Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>
>>> 2011/8/27 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
>>> > 2011/8/26 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>>> >> This patchset does a fairly major cleanup and overhaul of the receive
>>> >> codepath for cifs. Aside from basic cleanup, there are two main goals:
>>> >>
>>> >> 1) allow the receive codepath to identify the mid before receiving all
>>> >> of the data for a particular SMB.
>>> >>
>>> >> ...and in turn...
>>> >>
>>> >> 2) add the ability for certain calls to receive their responses into
>>> >> their into their own set of buffers.
>>> >>
>>> >> These two changes allow cifs to break the CIFSMaxBufSize barrier for
>>> >> receives. This patchset just adds the necessary infrastructure to do
>>> >> the above.
>>> >>
>>> >> A separate patchset will follow that will overhaul cifs_readpages to use
>>> >> this infrastructure to allow for a larger rsize.
>>> >>
>>> >> Jeff Layton (16):
>>> >>  cifs: clean up checkSMB
>>> >>  cifs: consolidate signature generating code
>>> >>  cifs: trivial: remove obsolete comment
>>> >>  cifs: make smb_msg local to read_from_socket
>>> >>  cifs: check for unresponsive server every time we call kernel_recvmsg
>>> >>  cifs: simplify read_from_socket
>>> >>  cifs: turn read_from_socket into a wrapper around a vectorized
>>> >>    version
>>> >>  cifs: keep a reusable kvec array for receives
>>> >>  cifs: clean up check_rfc1002_header
>>> >>  cifs: add a third receive phase to cifs_demultiplex_thread
>>> >>  cifs: move mid finding into separate routine
>>> >>  cifs: eliminate is_multi_rsp parm to find_cifs_mid
>>> >>  cifs: move buffer pointers into TCP_Server_Info
>>> >>  cifs: find mid earlier in receive codepath
>>> >>  cifs: break out 3rd receive phase into separate function
>>> >>  cifs: add a callback function to receive the rest of the frame
>>> >>
>>> >>  fs/cifs/cifsencrypt.c |  103 ++--------
>>> >>  fs/cifs/cifsglob.h    |   29 +++-
>>> >>  fs/cifs/cifsproto.h   |    7 +-
>>> >>  fs/cifs/cifssmb.c     |    5 +-
>>> >>  fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
>>> >>  fs/cifs/misc.c        |   51 +++---
>>> >>  fs/cifs/transport.c   |   16 +-
>>> >>  7 files changed, 391 insertions(+), 339 deletions(-)
>>> >>
>>> >> --
>>> >> 1.7.6
>>> >>
>>> >> --
>>> >> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
>>> >> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>> >>
>>> >
>>> > The patchset looks good to me at the first glance. I am going to look
>>> > at this more carefully and test it in a few days.
>>> >
>>> > --
>>> > Best regards,
>>> > Pavel Shilovsky.
>>> >
>>>
>>> Sorry for the long delay on this. As patchwork.kernel.org isn't
>>> available now, can you point me to public git repo, where I can fetch
>>> that changes, please?
>>>
>>
>>
>> Yes, I've moved my git repo to samba.org for the time being:
>>
>> http://git.samba.org/?p=jlayton/linux.git;a=summary
>>
>> See the "cifs-3.2" branch.
>>
>> --
>> Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>
>
> I successfully tested this - the performance was closed to write one
> in my case - about 11.5 MB on 100Mbit LAN against Windows 7 server.

Sorry for the type - "about 11.5 MB/s"

> Seems like a very good work!
>
> --
> Best regards,
> Pavel Shilovsky.
>



-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2)
       [not found]                     ` <CAKywueT3irL0zebNrxa_ErPLbT6NMgELos9e6dTe-0iPM4gz6A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-10-11 10:34                       ` Jeff Layton
  0 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-10-11 10:34 UTC (permalink / raw)
  To: Pavel Shilovsky
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Tue, 11 Oct 2011 14:16:36 +0400
Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

> 2011/10/11 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> > 2011/10/4 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> >> On Tue, 4 Oct 2011 13:04:19 +0400
> >> Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >>
> >>> 2011/8/27 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> >>> > 2011/8/26 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> >>> >> This patchset does a fairly major cleanup and overhaul of the receive
> >>> >> codepath for cifs. Aside from basic cleanup, there are two main goals:
> >>> >>
> >>> >> 1) allow the receive codepath to identify the mid before receiving all
> >>> >> of the data for a particular SMB.
> >>> >>
> >>> >> ...and in turn...
> >>> >>
> >>> >> 2) add the ability for certain calls to receive their responses into
> >>> >> their into their own set of buffers.
> >>> >>
> >>> >> These two changes allow cifs to break the CIFSMaxBufSize barrier for
> >>> >> receives. This patchset just adds the necessary infrastructure to do
> >>> >> the above.
> >>> >>
> >>> >> A separate patchset will follow that will overhaul cifs_readpages to use
> >>> >> this infrastructure to allow for a larger rsize.
> >>> >>
> >>> >> Jeff Layton (16):
> >>> >>  cifs: clean up checkSMB
> >>> >>  cifs: consolidate signature generating code
> >>> >>  cifs: trivial: remove obsolete comment
> >>> >>  cifs: make smb_msg local to read_from_socket
> >>> >>  cifs: check for unresponsive server every time we call kernel_recvmsg
> >>> >>  cifs: simplify read_from_socket
> >>> >>  cifs: turn read_from_socket into a wrapper around a vectorized
> >>> >>    version
> >>> >>  cifs: keep a reusable kvec array for receives
> >>> >>  cifs: clean up check_rfc1002_header
> >>> >>  cifs: add a third receive phase to cifs_demultiplex_thread
> >>> >>  cifs: move mid finding into separate routine
> >>> >>  cifs: eliminate is_multi_rsp parm to find_cifs_mid
> >>> >>  cifs: move buffer pointers into TCP_Server_Info
> >>> >>  cifs: find mid earlier in receive codepath
> >>> >>  cifs: break out 3rd receive phase into separate function
> >>> >>  cifs: add a callback function to receive the rest of the frame
> >>> >>
> >>> >>  fs/cifs/cifsencrypt.c |  103 ++--------
> >>> >>  fs/cifs/cifsglob.h    |   29 +++-
> >>> >>  fs/cifs/cifsproto.h   |    7 +-
> >>> >>  fs/cifs/cifssmb.c     |    5 +-
> >>> >>  fs/cifs/connect.c     |  519 ++++++++++++++++++++++++++++---------------------
> >>> >>  fs/cifs/misc.c        |   51 +++---
> >>> >>  fs/cifs/transport.c   |   16 +-
> >>> >>  7 files changed, 391 insertions(+), 339 deletions(-)
> >>> >>
> >>> >> --
> >>> >> 1.7.6
> >>> >>
> >>> >> --
> >>> >> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> >>> >> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> >>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>> >>
> >>> >
> >>> > The patchset looks good to me at the first glance. I am going to look
> >>> > at this more carefully and test it in a few days.
> >>> >
> >>> > --
> >>> > Best regards,
> >>> > Pavel Shilovsky.
> >>> >
> >>>
> >>> Sorry for the long delay on this. As patchwork.kernel.org isn't
> >>> available now, can you point me to public git repo, where I can fetch
> >>> that changes, please?
> >>>
> >>
> >>
> >> Yes, I've moved my git repo to samba.org for the time being:
> >>
> >> http://git.samba.org/?p=jlayton/linux.git;a=summary
> >>
> >> See the "cifs-3.2" branch.
> >>
> >> --
> >> Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> >>
> >
> > I successfully tested this - the performance was closed to write one
> > in my case - about 11.5 MB on 100Mbit LAN against Windows 7 server.
> 
> Sorry for the type - "about 11.5 MB/s"
> 
> > Seems like a very good work!
> >

Thanks for testing them! That's about what I get too. Working against
samba is much faster since we can negotiate a much larger rsize/wsize.

Thanks,
-- 
Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 05/16] cifs: check for unresponsive server every time we call kernel_recvmsg
       [not found] ` <1314616624-5362-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2011-08-29 11:16   ` Jeff Layton
  0 siblings, 0 replies; 24+ messages in thread
From: Jeff Layton @ 2011-08-29 11:16 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

If the server stops sending data while in the middle of sending a
response then we still want to reconnect it if it doesn't come back.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/connect.c |   33 ++++++++++++++++++++++-----------
 1 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d94eb32..720a619 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -358,6 +358,23 @@ allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
 	return true;
 }
 
+static bool
+server_unresponsive(struct TCP_Server_Info *server)
+{
+	if (echo_retries > 0 && server->tcpStatus == CifsGood &&
+	    time_after(jiffies, server->lstrp +
+				(echo_retries * SMB_ECHO_INTERVAL))) {
+		cERROR(1, "Server %s has not responded in %d seconds. "
+			  "Reconnecting...", server->hostname,
+			  (echo_retries * SMB_ECHO_INTERVAL / HZ));
+		cifs_reconnect(server);
+		wake_up(&server->response_q);
+		return true;
+	}
+
+	return false;
+}
+
 static int
 read_from_socket(struct TCP_Server_Info *server,
 		 struct kvec *iov, unsigned int to_read,
@@ -372,6 +389,11 @@ read_from_socket(struct TCP_Server_Info *server,
 	smb_msg.msg_controllen = 0;
 
 	for (total_read = 0; total_read < to_read; total_read += length) {
+		if (server_unresponsive(server)) {
+			rc = 1;
+			break;
+		}
+
 		length = kernel_recvmsg(server->ssocket, &smb_msg, iov, 1,
 					to_read - total_read, 0);
 		if (server->tcpStatus == CifsExiting) {
@@ -669,17 +691,6 @@ cifs_demultiplex_thread(void *p)
 		pdu_length = 4; /* enough to get RFC1001 header */
 
 incomplete_rcv:
-		if (echo_retries > 0 && server->tcpStatus == CifsGood &&
-		    time_after(jiffies, server->lstrp +
-					(echo_retries * SMB_ECHO_INTERVAL))) {
-			cERROR(1, "Server %s has not responded in %d seconds. "
-				  "Reconnecting...", server->hostname,
-				  (echo_retries * SMB_ECHO_INTERVAL / HZ));
-			cifs_reconnect(server);
-			wake_up(&server->response_q);
-			continue;
-		}
-
 		rc = read_from_socket(server, &iov, pdu_length,
 				      &total_read, true /* header read */);
 		if (rc == 3)
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2011-10-11 10:34 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-26 19:06 [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2) Jeff Layton
     [not found] ` <1314385589-27136-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2011-08-26 19:06   ` [PATCH 01/16] cifs: clean up checkSMB Jeff Layton
2011-08-26 19:06   ` [PATCH 02/16] cifs: consolidate signature generating code Jeff Layton
2011-08-26 19:06   ` [PATCH 03/16] cifs: trivial: remove obsolete comment Jeff Layton
2011-08-26 19:06   ` [PATCH 04/16] cifs: make smb_msg local to read_from_socket Jeff Layton
2011-08-26 19:06   ` [PATCH 05/16] cifs: check for unresponsive server every time we call kernel_recvmsg Jeff Layton
2011-08-26 19:06   ` [PATCH 06/16] cifs: simplify read_from_socket Jeff Layton
2011-08-26 19:06   ` [PATCH 07/16] cifs: turn read_from_socket into a wrapper around a vectorized version Jeff Layton
2011-08-26 19:06   ` [PATCH 08/16] cifs: keep a reusable kvec array for receives Jeff Layton
2011-08-26 19:06   ` [PATCH 09/16] cifs: clean up check_rfc1002_header Jeff Layton
2011-08-26 19:06   ` [PATCH 10/16] cifs: add a third receive phase to cifs_demultiplex_thread Jeff Layton
2011-08-26 19:06   ` [PATCH 11/16] cifs: move mid finding into separate routine Jeff Layton
2011-08-26 19:06   ` [PATCH 12/16] cifs: eliminate is_multi_rsp parm to find_cifs_mid Jeff Layton
2011-08-26 19:06   ` [PATCH 13/16] cifs: move buffer pointers into TCP_Server_Info Jeff Layton
2011-08-26 19:06   ` [PATCH 14/16] cifs: find mid earlier in receive codepath Jeff Layton
2011-08-26 19:06   ` [PATCH 15/16] cifs: break out 3rd receive phase into separate function Jeff Layton
2011-08-26 19:06   ` [PATCH 16/16] cifs: add a callback function to receive the rest of the frame Jeff Layton
2011-08-27 18:47   ` [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #2) Pavel Shilovsky
     [not found]     ` <CAKywueRCK+sw=GHBVn-mWe_Z1aWCH6uW=e=5MX7NNPY8Kum9tw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-04  9:04       ` Pavel Shilovsky
     [not found]         ` <CAKywueSboCYDxOF2a=Q0eLsKwWuai6BU5mnzAt_C_vjFkhSufw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-04 11:00           ` Jeff Layton
     [not found]             ` <20111004070058.7d3cf2bf-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2011-10-11 10:09               ` Pavel Shilovsky
     [not found]                 ` <CAKywueTByfFjDkMP8x5A8EJktqfKitbdipofujqJCwC5MknEuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-11 10:16                   ` Pavel Shilovsky
     [not found]                     ` <CAKywueT3irL0zebNrxa_ErPLbT6NMgELos9e6dTe-0iPM4gz6A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-11 10:34                       ` Jeff Layton
2011-08-29 11:16 [PATCH 00/16] cifs: cleanup and overhaul of the receive codepath (try #3) Jeff Layton
     [not found] ` <1314616624-5362-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2011-08-29 11:16   ` [PATCH 05/16] cifs: check for unresponsive server every time we call kernel_recvmsg Jeff Layton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.