All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] cifs: convert async write code to use less kmapping
@ 2012-07-18 17:58 Jeff Layton
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:58 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

We currently have a problem with the async write code on CONFIG_HIGHMEM
architectures. It uses *way* too much kmap space. Not only does this
limit throughput by adding an artificial bottleneck, but it also can
lead to deadlocks.

Late in the 3.5 cycle, I sent some patches to limit the rsize and wsize
on these arches as a temporary workaround. This patchset is a first pass
at fixing this the right way, by teaching the low-level transport code
how to deal with arrays of pages.

Note that this is just a fix for the write codepaths. The read side will
need a separate set of patches.

The code seems to work correctly, and is probably suitable for the
upcoming 3.6 merge window. This probably also has some non-trivial
conflicts with Pavel's patches since I did not base this on top of his
SMB2 work.

Let me know what you plan to merge first for 3.6 and I can try to
fix those up, or we can ask Pavel to rebase his code on top of this.

Jeff Layton (11):
  cifs: remove bogus reset of smb_buf_length in smb_send routines
  cifs: rename cifs_sign_smb2 to cifs_sign_smbv
  cifs: change signing routines to deal with smb_rqst structs
  cifs: convert send code to use smb_rqst structs
  cifs: cork the socket before a send and uncork it afterward
  cifs: teach smb_send_rqst how to handle arrays of pages
  cifs: teach signing routines how to deal with arrays of pages in a
    smb_rqst
  cifs: change cifs_call_async to use smb_rqst structs
  cifs: convert async write code to pass in data via rq_pages array
  cifs: remove the kmap size limit from wsize
  cifs: add deprecation warning to sockopt=TCP_NODELAY option

 fs/cifs/cifsencrypt.c |   39 +++++++--
 fs/cifs/cifsproto.h   |   37 ++++++--
 fs/cifs/cifssmb.c     |   53 ++++++------
 fs/cifs/connect.c     |   10 ++-
 fs/cifs/file.c        |   47 ++--------
 fs/cifs/transport.c   |  227 ++++++++++++++++++++++++++++++++++++-------------
 6 files changed, 264 insertions(+), 149 deletions(-)

-- 
1.7.10.4

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

* [PATCH 01/11] cifs: remove bogus reset of smb_buf_length in smb_send routines
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-18 17:58   ` Jeff Layton
       [not found]     ` <1342634346-22818-2-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:58   ` [PATCH 02/11] cifs: rename cifs_sign_smb2 to cifs_sign_smbv Jeff Layton
                     ` (10 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:58 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

There's a comment here about how we don't want to modify this length,
but nothing in this function actually does.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/transport.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 3097ee5..fa51913 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -126,7 +126,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 	int rc = 0;
 	int i = 0;
 	struct msghdr smb_msg;
-	__be32 *buf_len = (__be32 *)(iov[0].iov_base);
 	unsigned int len = iov[0].iov_len;
 	unsigned int total_len;
 	int first_vec = 0;
@@ -235,9 +234,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 	else
 		rc = 0;
 
-	/* Don't want to modify the buffer as a side effect of this call. */
-	*buf_len = cpu_to_be32(smb_buf_length);
-
 	return rc;
 }
 
-- 
1.7.10.4

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

* [PATCH 02/11] cifs: rename cifs_sign_smb2 to cifs_sign_smbv
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:58   ` [PATCH 01/11] cifs: remove bogus reset of smb_buf_length in smb_send routines Jeff Layton
@ 2012-07-18 17:58   ` Jeff Layton
       [not found]     ` <1342634346-22818-3-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:58   ` [PATCH 03/11] cifs: change signing routines to deal with smb_rqst structs Jeff Layton
                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:58 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

"smb2" makes me think of the SMB2.x protocol, which isn't at all what
this function is for...

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

diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index db768cb..6a0d741 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -99,7 +99,7 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
 }
 
 /* must be called with server->srv_mutex held */
-int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
+int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
 		   __u32 *pexpected_response_sequence_number)
 {
 	int rc = 0;
@@ -143,7 +143,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
 	iov.iov_base = cifs_pdu;
 	iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
 
-	return cifs_sign_smb2(&iov, 1, server,
+	return cifs_sign_smbv(&iov, 1, server,
 			      pexpected_response_sequence_number);
 }
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0a6cbfe..b09aa22 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -398,7 +398,7 @@ extern struct cifs_tcon *tconInfoAlloc(void);
 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 *,
+extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
 extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
 				 struct TCP_Server_Info *server,
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index fa51913..462130d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -366,7 +366,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
 	list_add_tail(&mid->qhead, &server->pending_mid_q);
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
+	rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
 	if (rc)
 		delete_mid(mid);
 	*ret_mid = mid;
@@ -522,7 +522,7 @@ cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
 	rc = allocate_mid(ses, hdr, &mid);
 	if (rc)
 		return rc;
-	rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number);
+	rc = cifs_sign_smbv(iov, nvec, ses->server, &mid->sequence_number);
 	if (rc)
 		delete_mid(mid);
 	*ret_mid = mid;
-- 
1.7.10.4

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

* [PATCH 03/11] cifs: change signing routines to deal with smb_rqst structs
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:58   ` [PATCH 01/11] cifs: remove bogus reset of smb_buf_length in smb_send routines Jeff Layton
  2012-07-18 17:58   ` [PATCH 02/11] cifs: rename cifs_sign_smb2 to cifs_sign_smbv Jeff Layton
@ 2012-07-18 17:58   ` Jeff Layton
       [not found]     ` <1342634346-22818-4-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:58   ` [PATCH 04/11] cifs: convert send code to use " Jeff Layton
                     ` (8 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:58 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

We need a way to represent a call to be sent on the wire that does not
require having all of the page data kmapped. Behold the smb_rqst struct.
This new struct represents an array of kvecs immediately followed by an
array of pages.

Convert the signing routines to use these structs under the hood and
turn the existing functions for this into wrappers around that. For now,
we're just changing these functions to take different args. Later, we'll
teach them how to deal with arrays of pages.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsencrypt.c |   26 ++++++++++++++++++--------
 fs/cifs/cifsproto.h   |   20 ++++++++++++++++++--
 fs/cifs/cifssmb.c     |    6 ++++--
 fs/cifs/transport.c   |    4 +++-
 4 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 6a0d741..e8953a0 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,11 +37,13 @@
  * the sequence number before this function is called. Also, this function
  * should be called with the server->srv_mutex held.
  */
-static int cifs_calc_signature(const struct kvec *iov, int n_vec,
+static int cifs_calc_signature(struct smb_rqst *rqst,
 			struct TCP_Server_Info *server, char *signature)
 {
 	int i;
 	int rc;
+	struct kvec *iov = rqst->rq_iov;
+	int n_vec = rqst->rq_nvec;
 
 	if (iov == NULL || signature == NULL || server == NULL)
 		return -EINVAL;
@@ -99,12 +101,12 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
 }
 
 /* must be called with server->srv_mutex held */
-int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
+int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
 		   __u32 *pexpected_response_sequence_number)
 {
 	int rc = 0;
 	char smb_signature[20];
-	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
+	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
 
 	if ((cifs_pdu == NULL) || (server == NULL))
 		return -EINVAL;
@@ -125,7 +127,7 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
 	*pexpected_response_sequence_number = server->sequence_number++;
 	server->sequence_number++;
 
-	rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
+	rc = cifs_calc_signature(rqst, server, smb_signature);
 	if (rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
 	else
@@ -134,6 +136,15 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
 	return rc;
 }
 
+int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
+		   __u32 *pexpected_response_sequence)
+{
+	struct smb_rqst rqst = { .rq_iov = iov,
+				 .rq_nvec = n_vec };
+
+	return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
+}
+
 /* 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)
@@ -147,14 +158,14 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
 			      pexpected_response_sequence_number);
 }
 
-int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
+int cifs_verify_signature(struct smb_rqst *rqst,
 			  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;
+	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
 
 	if (cifs_pdu == NULL || server == NULL)
 		return -EINVAL;
@@ -186,8 +197,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
 	mutex_lock(&server->srv_mutex);
-	rc = cifs_calc_signature(iov, nr_iov, server,
-				 what_we_think_sig_should_be);
+	rc = cifs_calc_signature(rqst, 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 b09aa22..b59e066 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -397,10 +397,26 @@ extern void sesInfoFree(struct cifs_ses *);
 extern struct cifs_tcon *tconInfoAlloc(void);
 extern void tconInfoFree(struct cifs_tcon *);
 
-extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
+/*
+ * A smb_rqst represents a complete request to be issued to a server. It's
+ * formed by a kvec array, followed by an array of pages. Page data is assumed
+ * to start at the beginning of the first page.
+ */
+struct smb_rqst {
+	struct kvec	*rq_iov;	/* array of kvecs */
+	unsigned int	rq_nvec;	/* number of kvecs in array */
+	struct page	**rq_pages;	/* pointer to array of page ptrs */
+	unsigned int	rq_npages;	/* number pages in array */
+	unsigned int	rq_pagesz;	/* page size to use */
+	unsigned int	rq_tailsz;	/* length of last page */
+};
+
+extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
+		   __u32 *pexpected_response_sequence_number);
 extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
-extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
+extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
+extern int cifs_verify_signature(struct smb_rqst *rqst,
 				 struct TCP_Server_Info *server,
 				__u32 expected_sequence_number);
 extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 1a05ab0..c010c279 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1562,6 +1562,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
 	struct cifs_readdata *rdata = mid->callback_data;
 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
 	struct TCP_Server_Info *server = tcon->ses->server;
+	struct smb_rqst rqst = { .rq_iov = rdata->iov,
+				 .rq_nvec = rdata->nr_iov };
 
 	cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
 		mid->mid, mid->mid_state, rdata->result, rdata->bytes);
@@ -1571,8 +1573,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
 		/* result already set, check signature */
 		if (server->sec_mode &
 		    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
-			if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
-					  server, mid->sequence_number + 1))
+			if (cifs_verify_signature(&rqst, server,
+						  mid->sequence_number + 1))
 				cERROR(1, "Unexpected SMB signature");
 		}
 		/* FIXME: should this be counted toward the initiating task? */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 462130d..531da42 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -498,11 +498,13 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 	/* convert the length into a more usable form */
 	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
 		struct kvec iov;
+		struct smb_rqst rqst = { .rq_iov = &iov,
+					 .rq_nvec = 1 };
 
 		iov.iov_base = mid->resp_buf;
 		iov.iov_len = len;
 		/* FIXME: add code to kill session */
-		if (cifs_verify_signature(&iov, 1, server,
+		if (cifs_verify_signature(&rqst, server,
 					  mid->sequence_number + 1) != 0)
 			cERROR(1, "Unexpected SMB signature");
 	}
-- 
1.7.10.4

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

* [PATCH 04/11] cifs: convert send code to use smb_rqst structs
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2012-07-18 17:58   ` [PATCH 03/11] cifs: change signing routines to deal with smb_rqst structs Jeff Layton
@ 2012-07-18 17:58   ` Jeff Layton
       [not found]     ` <1342634346-22818-5-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 05/11] cifs: cork the socket before a send and uncork it afterward Jeff Layton
                     ` (7 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:58 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Again, just a change in the arguments and some function renaming here.
In later patches, we'll change this code to deal with page arrays.

In this patch, we add a new smb_send_rqst wrapper and have smb_sendv
call that. Then we move most of the existing smb_sendv code into a new
function -- smb_send_kvec. This seems a little redundant, but later
we'll flesh this out to deal with arrays of pages.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/transport.c |  135 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 90 insertions(+), 45 deletions(-)

diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 531da42..5a1d817 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -120,18 +120,29 @@ delete_mid(struct mid_q_entry *mid)
 	DeleteMidQEntry(mid);
 }
 
+/*
+ * smb_send_kvec - send an array of kvecs to the server
+ * @server:	Server to send the data to
+ * @iov:	Pointer to array of kvecs
+ * @n_vec:	length of kvec array
+ * @sent:	amount of data sent on socket is stored here
+ *
+ * Our basic "send data to server" function. Should be called with srv_mutex
+ * held. The caller is responsible for handling the results.
+ */
 static int
-smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
+smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
+		size_t *sent)
 {
 	int rc = 0;
 	int i = 0;
 	struct msghdr smb_msg;
-	unsigned int len = iov[0].iov_len;
-	unsigned int total_len;
-	int first_vec = 0;
-	unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
+	unsigned int remaining;
+	size_t first_vec = 0;
 	struct socket *ssocket = server->ssocket;
 
+	*sent = 0;
+
 	if (ssocket == NULL)
 		return -ENOTSOCK; /* BB eventually add reconnect code here */
 
@@ -144,56 +155,60 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 	else
 		smb_msg.msg_flags = MSG_NOSIGNAL;
 
-	total_len = 0;
+	remaining = 0;
 	for (i = 0; i < n_vec; i++)
-		total_len += iov[i].iov_len;
-
-	cFYI(1, "Sending smb:  total_len %d", total_len);
-	dump_smb(iov[0].iov_base, len);
+		remaining += iov[i].iov_len;
 
 	i = 0;
-	while (total_len) {
+	while (remaining) {
+		/*
+		 * If blocking send, we try 3 times, since each can block
+		 * for 5 seconds. For nonblocking  we have to try more
+		 * but wait increasing amounts of time allowing time for
+		 * socket to clear.  The overall time we wait in either
+		 * case to send on the socket is about 15 seconds.
+		 * Similarly we wait for 15 seconds for a response from
+		 * the server in SendReceive[2] for the server to send
+		 * a response back for most types of requests (except
+		 * SMB Write past end of file which can be slow, and
+		 * blocking lock operations). NFS waits slightly longer
+		 * than CIFS, but this can make it take longer for
+		 * nonresponsive servers to be detected and 15 seconds
+		 * is more than enough time for modern networks to
+		 * send a packet.  In most cases if we fail to send
+		 * after the retries we will kill the socket and
+		 * reconnect which may clear the network problem.
+		 */
 		rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
-				    n_vec - first_vec, total_len);
-		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+				    n_vec - first_vec, remaining);
+		if (rc == -ENOSPC || rc == -EAGAIN) {
 			i++;
-			/*
-			 * If blocking send we try 3 times, since each can block
-			 * for 5 seconds. For nonblocking  we have to try more
-			 * but wait increasing amounts of time allowing time for
-			 * socket to clear.  The overall time we wait in either
-			 * case to send on the socket is about 15 seconds.
-			 * Similarly we wait for 15 seconds for a response from
-			 * the server in SendReceive[2] for the server to send
-			 * a response back for most types of requests (except
-			 * SMB Write past end of file which can be slow, and
-			 * blocking lock operations). NFS waits slightly longer
-			 * than CIFS, but this can make it take longer for
-			 * nonresponsive servers to be detected and 15 seconds
-			 * is more than enough time for modern networks to
-			 * send a packet.  In most cases if we fail to send
-			 * after the retries we will kill the socket and
-			 * reconnect which may clear the network problem.
-			 */
-			if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
-				cERROR(1, "sends on sock %p stuck for 15 seconds",
-				    ssocket);
+			if (i >= 14 || (!server->noblocksnd && (i > 2))) {
+				cERROR(1, "sends on sock %p stuck for 15 "
+					  "seconds", ssocket);
 				rc = -EAGAIN;
 				break;
 			}
 			msleep(1 << i);
 			continue;
 		}
+
 		if (rc < 0)
 			break;
 
-		if (rc == total_len) {
-			total_len = 0;
+		/* send was at least partially successful */
+		*sent += rc;
+
+		if (rc == remaining) {
+			remaining = 0;
 			break;
-		} else if (rc > total_len) {
-			cERROR(1, "sent %d requested %d", rc, total_len);
+		}
+
+		if (rc > remaining) {
+			cERROR(1, "sent %d requested %d", rc, remaining);
 			break;
 		}
+
 		if (rc == 0) {
 			/* should never happen, letting socket clear before
 			   retrying is our only obvious option here */
@@ -201,7 +216,9 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 			msleep(500);
 			continue;
 		}
-		total_len -= rc;
+
+		remaining -= rc;
+
 		/* the line below resets i */
 		for (i = first_vec; i < n_vec; i++) {
 			if (iov[i].iov_len) {
@@ -216,16 +233,35 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 				}
 			}
 		}
+
 		i = 0; /* in case we get ENOSPC on the next send */
+		rc = 0;
 	}
+	return rc;
+}
+
+static int
+smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
+{
+	int rc;
+	struct kvec *iov = rqst->rq_iov;
+	int n_vec = rqst->rq_nvec;
+	unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
+	size_t total_len;
+
+	cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
+	dump_smb(iov[0].iov_base, iov[0].iov_len);
+
+	rc = smb_send_kvec(server, iov, n_vec, &total_len);
 
 	if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
-		cFYI(1, "partial send (%d remaining), terminating session",
-			total_len);
-		/* If we have only sent part of an SMB then the next SMB
-		   could be taken as the remainder of this one.  We need
-		   to kill the socket so the server throws away the partial
-		   SMB */
+		cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
+			"session", smb_buf_length + 4, total_len);
+		/*
+		 * If we have only sent part of an SMB then the next SMB could
+		 * be taken as the remainder of this one. We need to kill the
+		 * socket so the server throws away the partial SMB
+		 */
 		server->tcpStatus = CifsNeedReconnect;
 	}
 
@@ -237,6 +273,15 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 	return rc;
 }
 
+static int
+smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
+{
+	struct smb_rqst rqst = { .rq_iov = iov,
+				 .rq_nvec = n_vec };
+
+	return smb_send_rqst(server, &rqst);
+}
+
 int
 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
 	 unsigned int smb_buf_length)
-- 
1.7.10.4

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

* [PATCH 05/11] cifs: cork the socket before a send and uncork it afterward
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (3 preceding siblings ...)
  2012-07-18 17:58   ` [PATCH 04/11] cifs: convert send code to use " Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-6-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 06/11] cifs: teach smb_send_rqst how to handle arrays of pages Jeff Layton
                     ` (6 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

We want to send SMBs as "atomically" as possible. Prior to sending any
data on the socket, cork it to make sure that no non-full frames go
out. Afterward, uncork it to make sure all of the data gets pushed out
to the wire.

Note that this more or less renders the socket=TCP_NODELAY mount option
obsolete. When TCP_CORK and TCP_NODELAY are used on the same socket,
TCP_NODELAY is essentially ignored.

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

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e8c3e6b..99ca139 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1830,6 +1830,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			if (string == NULL)
 				goto out_nomem;
 
+			/*
+			 * FIXME: since we now cork/uncork the socket while
+			 * 	  sending, should we deprecate this option?
+			 */
 			if (strnicmp(string, "TCP_NODELAY", 11) == 0)
 				vol->sockopt_tcp_nodelay = 1;
 			break;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 5a1d817..af56e91 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -27,6 +27,7 @@
 #include <linux/net.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
+#include <linux/tcp.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <linux/mempool.h>
@@ -248,12 +249,23 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	int n_vec = rqst->rq_nvec;
 	unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
 	size_t total_len;
+	struct socket *ssocket = server->ssocket;
+	int val = 1;
 
 	cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
 	dump_smb(iov[0].iov_base, iov[0].iov_len);
 
+	/* cork the socket */
+	kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
+				(char *)&val, sizeof(val));
+
 	rc = smb_send_kvec(server, iov, n_vec, &total_len);
 
+	/* uncork it */
+	val = 0;
+	kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
+				(char *)&val, sizeof(val));
+
 	if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
 		cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
 			"session", smb_buf_length + 4, total_len);
-- 
1.7.10.4

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

* [PATCH 06/11] cifs: teach smb_send_rqst how to handle arrays of pages
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (4 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 05/11] cifs: cork the socket before a send and uncork it afterward Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-7-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 07/11] cifs: teach signing routines how to deal with arrays of pages in a smb_rqst Jeff Layton
                     ` (5 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Add code that allows smb_send_rqst to send an array of pages after the
initial kvec array has been sent. For now, we simply kmap the page
array and send it using the standard smb_send_kvec function. Eventually,
we may want to convert this code to use kernel_sendpage under the hood
and avoid the kmap altogether for the page data.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/transport.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index af56e91..006c3fb 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/freezer.h>
 #include <linux/tcp.h>
+#include <linux/highmem.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <linux/mempool.h>
@@ -241,6 +242,38 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
 	return rc;
 }
 
+/**
+ * rqst_page_to_kvec - Turn a slot in the smb_rqst page array into a kvec
+ * @rqst: pointer to smb_rqst
+ * @idx: index into the array of the page
+ * @iov: pointer to struct kvec that will hold the result
+ *
+ * Helper function to convert a slot in the rqst->rq_pages array into a kvec.
+ * The page will be kmapped and the address placed into iov_base. The length
+ * will then be adjusted according to the ptailoff.
+ */
+static void
+cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
+			struct kvec *iov)
+{
+	/*
+	 * FIXME: We could avoid this kmap altogether if we used
+	 * kernel_sendpage instead of kernel_sendmsg. That will only
+	 * work if signing is disabled though as sendpage inlines the
+	 * page directly into the fraglist. If userspace modifies the
+	 * page after we calculate the signature, then the server will
+	 * reject it and may break the connection. kernel_sendmsg does
+	 * an extra copy of the data and avoids that issue.
+	 */
+	iov->iov_base = kmap(rqst->rq_pages[idx]);
+
+	/* if last page, don't send beyond this offset into page */
+	if (idx == (rqst->rq_npages - 1))
+		iov->iov_len = rqst->rq_tailsz;
+	else
+		iov->iov_len = rqst->rq_pagesz;
+}
+
 static int
 smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 {
@@ -248,7 +281,8 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	struct kvec *iov = rqst->rq_iov;
 	int n_vec = rqst->rq_nvec;
 	unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
-	size_t total_len;
+	unsigned int i;
+	size_t total_len = 0, sent;
 	struct socket *ssocket = server->ssocket;
 	int val = 1;
 
@@ -259,8 +293,26 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
 				(char *)&val, sizeof(val));
 
-	rc = smb_send_kvec(server, iov, n_vec, &total_len);
+	rc = smb_send_kvec(server, iov, n_vec, &sent);
+	if (rc < 0)
+		goto uncork;
+
+	total_len += sent;
+
+	/* now walk the page array and send each page in it */
+	for (i = 0; i < rqst->rq_npages; i++) {
+		struct kvec p_iov;
+
+		cifs_rqst_page_to_kvec(rqst, i, &p_iov);
+		rc = smb_send_kvec(server, &p_iov, 1, &sent);
+		kunmap(rqst->rq_pages[i]);
+		if (rc < 0)
+			break;
+
+		total_len += sent;
+	}
 
+uncork:
 	/* uncork it */
 	val = 0;
 	kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
-- 
1.7.10.4

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

* [PATCH 07/11] cifs: teach signing routines how to deal with arrays of pages in a smb_rqst
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (5 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 06/11] cifs: teach smb_send_rqst how to handle arrays of pages Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-8-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 08/11] cifs: change cifs_call_async to use smb_rqst structs Jeff Layton
                     ` (4 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Use the smb_send_rqst helper function to kmap each page in the array
and update the hash for that chunk.

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

diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index e8953a0..511d1ae 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -29,6 +29,7 @@
 #include "ntlmssp.h"
 #include <linux/ctype.h>
 #include <linux/random.h>
+#include <linux/highmem.h>
 
 /*
  * Calculate and return the CIFS signature based on the mac key and SMB PDU.
@@ -93,6 +94,16 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
 		}
 	}
 
+	/* now hash over the rq_pages array */
+	for (i = 0; i < rqst->rq_npages; i++) {
+		struct kvec p_iov;
+
+		cifs_rqst_page_to_kvec(rqst, i, &p_iov);
+		crypto_shash_update(&server->secmech.sdescmd5->shash,
+					p_iov.iov_base, p_iov.iov_len);
+		kunmap(rqst->rq_pages[i]);
+	}
+
 	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
 	if (rc)
 		cERROR(1, "%s: Could not generate md5 hash", __func__);
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b59e066..b2daad4 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -24,6 +24,7 @@
 
 struct statfs;
 struct smb_vol;
+struct smb_rqst;
 
 /*
  *****************************************************************
@@ -35,6 +36,8 @@ extern struct smb_hdr *cifs_buf_get(void);
 extern void cifs_buf_release(void *);
 extern struct smb_hdr *cifs_small_buf_get(void);
 extern void cifs_small_buf_release(void *);
+extern void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
+					struct kvec *iov);
 extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
 			unsigned int /* length */);
 extern unsigned int _GetXid(void);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 006c3fb..8e689d1 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -252,7 +252,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
  * The page will be kmapped and the address placed into iov_base. The length
  * will then be adjusted according to the ptailoff.
  */
-static void
+void
 cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
 			struct kvec *iov)
 {
-- 
1.7.10.4

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

* [PATCH 08/11] cifs: change cifs_call_async to use smb_rqst structs
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (6 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 07/11] cifs: teach signing routines how to deal with arrays of pages in a smb_rqst Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-9-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 09/11] cifs: convert async write code to pass in data via rq_pages array Jeff Layton
                     ` (3 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

For now, none of the callers populate rq_pages. That will be done for
writes in a later patch.

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsproto.h |    8 ++++----
 fs/cifs/cifssmb.c   |   20 +++++++++++++-------
 fs/cifs/transport.c |   18 +++++++++---------
 3 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b2daad4..dbb9c61 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -71,10 +71,10 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
 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_receive_t *receive,
-			   mid_callback_t *callback, void *cbdata,
-			   bool ignore_pend);
+extern int cifs_call_async(struct TCP_Server_Info *server,
+			struct smb_rqst *rqst, 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 c010c279..727f35e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -753,6 +753,8 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
 	ECHO_REQ *smb;
 	int rc = 0;
 	struct kvec iov;
+	struct smb_rqst rqst = { .rq_iov = &iov,
+				 .rq_nvec = 1 };
 
 	cFYI(1, "In echo request");
 
@@ -770,7 +772,7 @@ 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, NULL, cifs_echo_callback,
+	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
 			     server, true);
 	if (rc)
 		cFYI(1, "Echo request failed: %d", rc);
@@ -1602,6 +1604,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
 	READ_REQ *smb = NULL;
 	int wct;
 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+	struct smb_rqst rqst = { .rq_iov = rdata->iov,
+				 .rq_nvec = 1 };
 
 	cFYI(1, "%s: offset=%llu bytes=%u", __func__,
 		rdata->offset, rdata->bytes);
@@ -1645,9 +1649,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
 	rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
 
 	kref_get(&rdata->refcount);
-	rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
-			     cifs_readv_receive, cifs_readv_callback,
-			     rdata, false);
+	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
+			     cifs_readv_callback, rdata, false);
 
 	if (rc == 0)
 		cifs_stats_inc(&tcon->num_reads);
@@ -2050,6 +2053,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	int wct;
 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
 	struct kvec *iov = NULL;
+	struct smb_rqst rqst = { };
 
 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
 		wct = 14;
@@ -2066,11 +2070,13 @@ cifs_async_writev(struct cifs_writedata *wdata)
 		goto async_writev_out;
 
 	/* 1 iov per page + 1 for header */
-	iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
+	rqst.rq_nvec = wdata->nr_pages + 1;
+	iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
 	if (iov == NULL) {
 		rc = -ENOMEM;
 		goto async_writev_out;
 	}
+	rqst.rq_iov = iov;
 
 	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
@@ -2119,8 +2125,8 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	}
 
 	kref_get(&wdata->refcount);
-	rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
-			     NULL, cifs_writev_callback, wdata, false);
+	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
+				cifs_writev_callback, wdata, false);
 
 	if (rc == 0)
 		cifs_stats_inc(&tcon->num_writes);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 8e689d1..83a1489 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -455,11 +455,11 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
 }
 
 static int
-cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
-			 unsigned int nvec, struct mid_q_entry **ret_mid)
+cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst,
+			 struct mid_q_entry **ret_mid)
 {
 	int rc;
-	struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
+	struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
 	struct mid_q_entry *mid;
 
 	/* enable signing if server requires it */
@@ -475,7 +475,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
 	list_add_tail(&mid->qhead, &server->pending_mid_q);
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
+	rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
 	if (rc)
 		delete_mid(mid);
 	*ret_mid = mid;
@@ -487,9 +487,9 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
  * the result. Caller is responsible for dealing with timeouts.
  */
 int
-cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
-		unsigned int nvec, mid_receive_t *receive,
-		mid_callback_t *callback, void *cbdata, bool ignore_pend)
+cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
+		mid_receive_t *receive, mid_callback_t *callback,
+		void *cbdata, bool ignore_pend)
 {
 	int rc;
 	struct mid_q_entry *mid;
@@ -499,7 +499,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
 		return rc;
 
 	mutex_lock(&server->srv_mutex);
-	rc = cifs_setup_async_request(server, iov, nvec, &mid);
+	rc = cifs_setup_async_request(server, rqst, &mid);
 	if (rc) {
 		mutex_unlock(&server->srv_mutex);
 		add_credits(server, 1);
@@ -513,7 +513,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
 	mid->mid_state = MID_REQUEST_SUBMITTED;
 
 	cifs_in_send_inc(server);
-	rc = smb_sendv(server, iov, nvec);
+	rc = smb_send_rqst(server, rqst);
 	cifs_in_send_dec(server);
 	cifs_save_when_sent(mid);
 	mutex_unlock(&server->srv_mutex);
-- 
1.7.10.4

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

* [PATCH 09/11] cifs: convert async write code to pass in data via rq_pages array
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (7 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 08/11] cifs: change cifs_call_async to use smb_rqst structs Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-10-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 10/11] cifs: remove the kmap size limit from wsize Jeff Layton
                     ` (2 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsproto.h |    4 ++--
 fs/cifs/cifssmb.c   |   33 ++++++++++-----------------------
 fs/cifs/file.c      |   47 +++++++++--------------------------------------
 3 files changed, 21 insertions(+), 63 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index dbb9c61..64a4297 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -515,8 +515,8 @@ struct cifs_writedata {
 	pid_t				pid;
 	unsigned int			bytes;
 	int				result;
-	void (*marshal_iov) (struct kvec *iov,
-			     struct cifs_writedata *wdata);
+	unsigned int			pagesz;
+	unsigned int			tailsz;
 	unsigned int			nr_pages;
 	struct page			*pages[1];
 };
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 727f35e..cb7de86 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2052,7 +2052,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	WRITE_REQ *smb = NULL;
 	int wct;
 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-	struct kvec *iov = NULL;
+	struct kvec iov;
 	struct smb_rqst rqst = { };
 
 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -2069,15 +2069,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	if (rc)
 		goto async_writev_out;
 
-	/* 1 iov per page + 1 for header */
-	rqst.rq_nvec = wdata->nr_pages + 1;
-	iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
-	if (iov == NULL) {
-		rc = -ENOMEM;
-		goto async_writev_out;
-	}
-	rqst.rq_iov = iov;
-
 	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
 
@@ -2094,18 +2085,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
 
 	/* 4 for RFC1001 length + 1 for BCC */
-	iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
-	iov[0].iov_base = smb;
+	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
+	iov.iov_base = smb;
 
-	/*
-	 * This function should marshal up the page array into the kvec
-	 * array, reserving [0] for the header. It should kmap the pages
-	 * and set the iov_len properly for each one. It may also set
-	 * wdata->bytes too.
-	 */
-	cifs_kmap_lock();
-	wdata->marshal_iov(iov, wdata);
-	cifs_kmap_unlock();
+	rqst.rq_iov = &iov;
+	rqst.rq_nvec = 1;
+	rqst.rq_pages = wdata->pages;
+	rqst.rq_npages = wdata->nr_pages;
+	rqst.rq_pagesz = wdata->pagesz;
+	rqst.rq_tailsz = wdata->tailsz;
 
 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
 
@@ -2121,7 +2109,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
 				(struct smb_com_writex_req *)smb;
 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
 		put_bcc(wdata->bytes + 5, &smbw->hdr);
-		iov[0].iov_len += 4; /* pad bigger by four bytes */
+		iov.iov_len += 4; /* pad bigger by four bytes */
 	}
 
 	kref_get(&wdata->refcount);
@@ -2139,7 +2127,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
 
 async_writev_out:
 	cifs_small_buf_release(smb);
-	kfree(iov);
 	return rc;
 }
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dd28caa..d5f8c60 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1710,27 +1710,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
 	return rc;
 }
 
-/*
- * Marshal up the iov array, reserving the first one for the header. Also,
- * set wdata->bytes.
- */
-static void
-cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
-{
-	int i;
-	struct inode *inode = wdata->cfile->dentry->d_inode;
-	loff_t size = i_size_read(inode);
-
-	/* marshal up the pages into iov array */
-	wdata->bytes = 0;
-	for (i = 0; i < wdata->nr_pages; i++) {
-		iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
-					(loff_t)PAGE_CACHE_SIZE);
-		iov[i + 1].iov_base = kmap(wdata->pages[i]);
-		wdata->bytes += iov[i + 1].iov_len;
-	}
-}
-
 static int cifs_writepages(struct address_space *mapping,
 			   struct writeback_control *wbc)
 {
@@ -1740,6 +1719,7 @@ static int cifs_writepages(struct address_space *mapping,
 	struct cifs_writedata *wdata;
 	struct page *page;
 	int rc = 0;
+	loff_t isize = i_size_read(mapping->host);
 
 	/*
 	 * If wsize is smaller than the page cache size, default to writing
@@ -1844,7 +1824,7 @@ retry:
 			 */
 			set_page_writeback(page);
 
-			if (page_offset(page) >= mapping->host->i_size) {
+			if (page_offset(page) >= isize) {
 				done = true;
 				unlock_page(page);
 				end_page_writeback(page);
@@ -1875,7 +1855,11 @@ retry:
 		wdata->sync_mode = wbc->sync_mode;
 		wdata->nr_pages = nr_pages;
 		wdata->offset = page_offset(wdata->pages[0]);
-		wdata->marshal_iov = cifs_writepages_marshal_iov;
+		wdata->pagesz = PAGE_CACHE_SIZE;
+		wdata->tailsz = min(isize - page_offset(wdata->pages[nr_pages - 1]),
+					(loff_t)PAGE_CACHE_SIZE);
+		wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
+					wdata->tailsz;
 
 		do {
 			if (wdata->cfile != NULL)
@@ -2164,20 +2148,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
 }
 
 static void
-cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
-{
-	int i;
-	size_t bytes = wdata->bytes;
-
-	/* marshal up the pages into iov array */
-	for (i = 0; i < wdata->nr_pages; i++) {
-		iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
-		iov[i + 1].iov_base = kmap(wdata->pages[i]);
-		bytes -= iov[i + 1].iov_len;
-	}
-}
-
-static void
 cifs_uncached_writev_complete(struct work_struct *work)
 {
 	int i;
@@ -2290,7 +2260,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 		wdata->cfile = cifsFileInfo_get(open_file);
 		wdata->pid = pid;
 		wdata->bytes = cur_len;
-		wdata->marshal_iov = cifs_uncached_marshal_iov;
+		wdata->pagesz = PAGE_SIZE;
+		wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
 		rc = cifs_uncached_retry_writev(wdata);
 		if (rc) {
 			kref_put(&wdata->refcount, cifs_writedata_release);
-- 
1.7.10.4

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

* [PATCH 10/11] cifs: remove the kmap size limit from wsize
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (8 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 09/11] cifs: convert async write code to pass in data via rq_pages array Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-11-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-18 17:59   ` [PATCH 11/11] cifs: add deprecation warning to sockopt=TCP_NODELAY option Jeff Layton
  2012-07-24 19:23   ` [PATCH 00/11] cifs: convert async write code to use less kmapping Pavel Shilovsky
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Now that we're not kmapping so much at once, there's no need to cap
the wsize at the amount that can be simultaneously kmapped.

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

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 99ca139..303be53 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3491,9 +3491,6 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
 		wsize = min_t(unsigned int, wsize,
 				server->maxBuf - sizeof(WRITE_REQ) + 4);
 
-	/* limit to the amount that we can kmap at once */
-	wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
-
 	/* hard limit of CIFS_MAX_WSIZE */
 	wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
 
-- 
1.7.10.4

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

* [PATCH 11/11] cifs: add deprecation warning to sockopt=TCP_NODELAY option
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (9 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 10/11] cifs: remove the kmap size limit from wsize Jeff Layton
@ 2012-07-18 17:59   ` Jeff Layton
       [not found]     ` <1342634346-22818-12-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2012-07-24 19:23   ` [PATCH 00/11] cifs: convert async write code to use less kmapping Pavel Shilovsky
  11 siblings, 1 reply; 27+ messages in thread
From: Jeff Layton @ 2012-07-18 17:59 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Now that we're using TCP_CORK on the socket, there's no value in
continuting to support this option. Schedule it for removal in 3.8.

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

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 303be53..29d9716 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1830,12 +1830,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			if (string == NULL)
 				goto out_nomem;
 
-			/*
-			 * FIXME: since we now cork/uncork the socket while
-			 * 	  sending, should we deprecate this option?
-			 */
-			if (strnicmp(string, "TCP_NODELAY", 11) == 0)
+			if (strnicmp(string, "TCP_NODELAY", 11) == 0) {
+				printk(KERN_WARNING, "CIFS: the "
+					"sockopt=TCP_NODELAY option has been "
+					"deprecated and will be removed "
+					"in 3.8\n");
 				vol->sockopt_tcp_nodelay = 1;
+			}
 			break;
 		case Opt_netbiosname:
 			string = match_strdup(args);
-- 
1.7.10.4

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

* Re: [PATCH 09/11] cifs: convert async write code to pass in data via rq_pages array
       [not found]     ` <1342634346-22818-10-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-24  9:44       ` Pavel Shilovsky
       [not found]         ` <CAKywueTO3OCTV8M4Lo1kSpfZjyHDPDxRZthE-URkr=5=ow-Z2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-24  9:44 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/cifsproto.h |    4 ++--
>  fs/cifs/cifssmb.c   |   33 ++++++++++-----------------------
>  fs/cifs/file.c      |   47 +++++++++--------------------------------------
>  3 files changed, 21 insertions(+), 63 deletions(-)
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index dbb9c61..64a4297 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -515,8 +515,8 @@ struct cifs_writedata {
>         pid_t                           pid;
>         unsigned int                    bytes;
>         int                             result;
> -       void (*marshal_iov) (struct kvec *iov,
> -                            struct cifs_writedata *wdata);
> +       unsigned int                    pagesz;
> +       unsigned int                    tailsz;
>         unsigned int                    nr_pages;
>         struct page                     *pages[1];
>  };
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 727f35e..cb7de86 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -2052,7 +2052,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
>         WRITE_REQ *smb = NULL;
>         int wct;
>         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
> -       struct kvec *iov = NULL;
> +       struct kvec iov;
>         struct smb_rqst rqst = { };
>
>         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
> @@ -2069,15 +2069,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
>         if (rc)
>                 goto async_writev_out;
>
> -       /* 1 iov per page + 1 for header */
> -       rqst.rq_nvec = wdata->nr_pages + 1;
> -       iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
> -       if (iov == NULL) {
> -               rc = -ENOMEM;
> -               goto async_writev_out;
> -       }
> -       rqst.rq_iov = iov;
> -
>         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
>         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
>
> @@ -2094,18 +2085,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
>             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
>
>         /* 4 for RFC1001 length + 1 for BCC */
> -       iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
> -       iov[0].iov_base = smb;
> +       iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
> +       iov.iov_base = smb;
>
> -       /*
> -        * This function should marshal up the page array into the kvec
> -        * array, reserving [0] for the header. It should kmap the pages
> -        * and set the iov_len properly for each one. It may also set
> -        * wdata->bytes too.
> -        */
> -       cifs_kmap_lock();
> -       wdata->marshal_iov(iov, wdata);
> -       cifs_kmap_unlock();
> +       rqst.rq_iov = &iov;
> +       rqst.rq_nvec = 1;
> +       rqst.rq_pages = wdata->pages;
> +       rqst.rq_npages = wdata->nr_pages;
> +       rqst.rq_pagesz = wdata->pagesz;
> +       rqst.rq_tailsz = wdata->tailsz;

Now we are not kmapping here but still kunmaping below:

2105 >-------/* send is done, unmap pages */
2106 >-------for (i = 0; i < wdata->nr_pages; i++)
2107 >------->-------kunmap(wdata->pages[i]);

Is it ok? (seems like we've already kunmap'ed them in smb_send_rqst)

>
>         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
>
> @@ -2121,7 +2109,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
>                                 (struct smb_com_writex_req *)smb;
>                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
>                 put_bcc(wdata->bytes + 5, &smbw->hdr);
> -               iov[0].iov_len += 4; /* pad bigger by four bytes */
> +               iov.iov_len += 4; /* pad bigger by four bytes */
>         }
>
>         kref_get(&wdata->refcount);
> @@ -2139,7 +2127,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
>
>  async_writev_out:
>         cifs_small_buf_release(smb);
> -       kfree(iov);
>         return rc;
>  }
>
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index dd28caa..d5f8c60 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -1710,27 +1710,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
>         return rc;
>  }
>
> -/*
> - * Marshal up the iov array, reserving the first one for the header. Also,
> - * set wdata->bytes.
> - */
> -static void
> -cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
> -{
> -       int i;
> -       struct inode *inode = wdata->cfile->dentry->d_inode;
> -       loff_t size = i_size_read(inode);
> -
> -       /* marshal up the pages into iov array */
> -       wdata->bytes = 0;
> -       for (i = 0; i < wdata->nr_pages; i++) {
> -               iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
> -                                       (loff_t)PAGE_CACHE_SIZE);
> -               iov[i + 1].iov_base = kmap(wdata->pages[i]);
> -               wdata->bytes += iov[i + 1].iov_len;
> -       }
> -}
> -
>  static int cifs_writepages(struct address_space *mapping,
>                            struct writeback_control *wbc)
>  {
> @@ -1740,6 +1719,7 @@ static int cifs_writepages(struct address_space *mapping,
>         struct cifs_writedata *wdata;
>         struct page *page;
>         int rc = 0;
> +       loff_t isize = i_size_read(mapping->host);
>
>         /*
>          * If wsize is smaller than the page cache size, default to writing
> @@ -1844,7 +1824,7 @@ retry:
>                          */
>                         set_page_writeback(page);
>
> -                       if (page_offset(page) >= mapping->host->i_size) {
> +                       if (page_offset(page) >= isize) {
>                                 done = true;
>                                 unlock_page(page);
>                                 end_page_writeback(page);
> @@ -1875,7 +1855,11 @@ retry:
>                 wdata->sync_mode = wbc->sync_mode;
>                 wdata->nr_pages = nr_pages;
>                 wdata->offset = page_offset(wdata->pages[0]);
> -               wdata->marshal_iov = cifs_writepages_marshal_iov;
> +               wdata->pagesz = PAGE_CACHE_SIZE;
> +               wdata->tailsz = min(isize - page_offset(wdata->pages[nr_pages - 1]),
> +                                       (loff_t)PAGE_CACHE_SIZE);
> +               wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
> +                                       wdata->tailsz;
>
>                 do {
>                         if (wdata->cfile != NULL)
> @@ -2164,20 +2148,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
>  }
>
>  static void
> -cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
> -{
> -       int i;
> -       size_t bytes = wdata->bytes;
> -
> -       /* marshal up the pages into iov array */
> -       for (i = 0; i < wdata->nr_pages; i++) {
> -               iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
> -               iov[i + 1].iov_base = kmap(wdata->pages[i]);
> -               bytes -= iov[i + 1].iov_len;
> -       }
> -}
> -
> -static void
>  cifs_uncached_writev_complete(struct work_struct *work)
>  {
>         int i;
> @@ -2290,7 +2260,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
>                 wdata->cfile = cifsFileInfo_get(open_file);
>                 wdata->pid = pid;
>                 wdata->bytes = cur_len;
> -               wdata->marshal_iov = cifs_uncached_marshal_iov;
> +               wdata->pagesz = PAGE_SIZE;
> +               wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
>                 rc = cifs_uncached_retry_writev(wdata);
>                 if (rc) {
>                         kref_put(&wdata->refcount, cifs_writedata_release);
> --
> 1.7.10.4
>
> --
> 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



-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 09/11] cifs: convert async write code to pass in data via rq_pages array
       [not found]         ` <CAKywueTO3OCTV8M4Lo1kSpfZjyHDPDxRZthE-URkr=5=ow-Z2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-07-24 10:19           ` Jeff Layton
  2012-07-24 17:37           ` [PATCH v2 " Jeff Layton
  1 sibling, 0 replies; 27+ messages in thread
From: Jeff Layton @ 2012-07-24 10:19 UTC (permalink / raw)
  To: Pavel Shilovsky
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Tue, 24 Jul 2012 13:44:44 +0400
Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

> 2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> > Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> >  fs/cifs/cifsproto.h |    4 ++--
> >  fs/cifs/cifssmb.c   |   33 ++++++++++-----------------------
> >  fs/cifs/file.c      |   47 +++++++++--------------------------------------
> >  3 files changed, 21 insertions(+), 63 deletions(-)
> >
> > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> > index dbb9c61..64a4297 100644
> > --- a/fs/cifs/cifsproto.h
> > +++ b/fs/cifs/cifsproto.h
> > @@ -515,8 +515,8 @@ struct cifs_writedata {
> >         pid_t                           pid;
> >         unsigned int                    bytes;
> >         int                             result;
> > -       void (*marshal_iov) (struct kvec *iov,
> > -                            struct cifs_writedata *wdata);
> > +       unsigned int                    pagesz;
> > +       unsigned int                    tailsz;
> >         unsigned int                    nr_pages;
> >         struct page                     *pages[1];
> >  };
> > diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> > index 727f35e..cb7de86 100644
> > --- a/fs/cifs/cifssmb.c
> > +++ b/fs/cifs/cifssmb.c
> > @@ -2052,7 +2052,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
> >         WRITE_REQ *smb = NULL;
> >         int wct;
> >         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
> > -       struct kvec *iov = NULL;
> > +       struct kvec iov;
> >         struct smb_rqst rqst = { };
> >
> >         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
> > @@ -2069,15 +2069,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
> >         if (rc)
> >                 goto async_writev_out;
> >
> > -       /* 1 iov per page + 1 for header */
> > -       rqst.rq_nvec = wdata->nr_pages + 1;
> > -       iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
> > -       if (iov == NULL) {
> > -               rc = -ENOMEM;
> > -               goto async_writev_out;
> > -       }
> > -       rqst.rq_iov = iov;
> > -
> >         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
> >         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
> >
> > @@ -2094,18 +2085,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
> >             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
> >
> >         /* 4 for RFC1001 length + 1 for BCC */
> > -       iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
> > -       iov[0].iov_base = smb;
> > +       iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
> > +       iov.iov_base = smb;
> >
> > -       /*
> > -        * This function should marshal up the page array into the kvec
> > -        * array, reserving [0] for the header. It should kmap the pages
> > -        * and set the iov_len properly for each one. It may also set
> > -        * wdata->bytes too.
> > -        */
> > -       cifs_kmap_lock();
> > -       wdata->marshal_iov(iov, wdata);
> > -       cifs_kmap_unlock();
> > +       rqst.rq_iov = &iov;
> > +       rqst.rq_nvec = 1;
> > +       rqst.rq_pages = wdata->pages;
> > +       rqst.rq_npages = wdata->nr_pages;
> > +       rqst.rq_pagesz = wdata->pagesz;
> > +       rqst.rq_tailsz = wdata->tailsz;
> 
> Now we are not kmapping here but still kunmaping below:
> 
> 2105 >-------/* send is done, unmap pages */
> 2106 >-------for (i = 0; i < wdata->nr_pages; i++)
> 2107 >------->-------kunmap(wdata->pages[i]);
> 
> Is it ok? (seems like we've already kunmap'ed them in smb_send_rqst)
> 

Well spotted.

No that's not OK. We'll end up putting too many refs to it. I'll fix
and respin.

> >
> >         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
> >
> > @@ -2121,7 +2109,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
> >                                 (struct smb_com_writex_req *)smb;
> >                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
> >                 put_bcc(wdata->bytes + 5, &smbw->hdr);
> > -               iov[0].iov_len += 4; /* pad bigger by four bytes */
> > +               iov.iov_len += 4; /* pad bigger by four bytes */
> >         }
> >
> >         kref_get(&wdata->refcount);
> > @@ -2139,7 +2127,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
> >
> >  async_writev_out:
> >         cifs_small_buf_release(smb);
> > -       kfree(iov);
> >         return rc;
> >  }
> >
> > diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> > index dd28caa..d5f8c60 100644
> > --- a/fs/cifs/file.c
> > +++ b/fs/cifs/file.c
> > @@ -1710,27 +1710,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
> >         return rc;
> >  }
> >
> > -/*
> > - * Marshal up the iov array, reserving the first one for the header. Also,
> > - * set wdata->bytes.
> > - */
> > -static void
> > -cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
> > -{
> > -       int i;
> > -       struct inode *inode = wdata->cfile->dentry->d_inode;
> > -       loff_t size = i_size_read(inode);
> > -
> > -       /* marshal up the pages into iov array */
> > -       wdata->bytes = 0;
> > -       for (i = 0; i < wdata->nr_pages; i++) {
> > -               iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
> > -                                       (loff_t)PAGE_CACHE_SIZE);
> > -               iov[i + 1].iov_base = kmap(wdata->pages[i]);
> > -               wdata->bytes += iov[i + 1].iov_len;
> > -       }
> > -}
> > -
> >  static int cifs_writepages(struct address_space *mapping,
> >                            struct writeback_control *wbc)
> >  {
> > @@ -1740,6 +1719,7 @@ static int cifs_writepages(struct address_space *mapping,
> >         struct cifs_writedata *wdata;
> >         struct page *page;
> >         int rc = 0;
> > +       loff_t isize = i_size_read(mapping->host);
> >
> >         /*
> >          * If wsize is smaller than the page cache size, default to writing
> > @@ -1844,7 +1824,7 @@ retry:
> >                          */
> >                         set_page_writeback(page);
> >
> > -                       if (page_offset(page) >= mapping->host->i_size) {
> > +                       if (page_offset(page) >= isize) {
> >                                 done = true;
> >                                 unlock_page(page);
> >                                 end_page_writeback(page);
> > @@ -1875,7 +1855,11 @@ retry:
> >                 wdata->sync_mode = wbc->sync_mode;
> >                 wdata->nr_pages = nr_pages;
> >                 wdata->offset = page_offset(wdata->pages[0]);
> > -               wdata->marshal_iov = cifs_writepages_marshal_iov;
> > +               wdata->pagesz = PAGE_CACHE_SIZE;
> > +               wdata->tailsz = min(isize - page_offset(wdata->pages[nr_pages - 1]),
> > +                                       (loff_t)PAGE_CACHE_SIZE);
> > +               wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
> > +                                       wdata->tailsz;
> >
> >                 do {
> >                         if (wdata->cfile != NULL)
> > @@ -2164,20 +2148,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
> >  }
> >
> >  static void
> > -cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
> > -{
> > -       int i;
> > -       size_t bytes = wdata->bytes;
> > -
> > -       /* marshal up the pages into iov array */
> > -       for (i = 0; i < wdata->nr_pages; i++) {
> > -               iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
> > -               iov[i + 1].iov_base = kmap(wdata->pages[i]);
> > -               bytes -= iov[i + 1].iov_len;
> > -       }
> > -}
> > -
> > -static void
> >  cifs_uncached_writev_complete(struct work_struct *work)
> >  {
> >         int i;
> > @@ -2290,7 +2260,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
> >                 wdata->cfile = cifsFileInfo_get(open_file);
> >                 wdata->pid = pid;
> >                 wdata->bytes = cur_len;
> > -               wdata->marshal_iov = cifs_uncached_marshal_iov;
> > +               wdata->pagesz = PAGE_SIZE;
> > +               wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
> >                 rc = cifs_uncached_retry_writev(wdata);
> >                 if (rc) {
> >                         kref_put(&wdata->refcount, cifs_writedata_release);
> > --
> > 1.7.10.4
> >
> > --
> > 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
> 
> 
> 


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

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

* [PATCH v2 09/11] cifs: convert async write code to pass in data via rq_pages array
       [not found]         ` <CAKywueTO3OCTV8M4Lo1kSpfZjyHDPDxRZthE-URkr=5=ow-Z2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2012-07-24 10:19           ` Jeff Layton
@ 2012-07-24 17:37           ` Jeff Layton
  1 sibling, 0 replies; 27+ messages in thread
From: Jeff Layton @ 2012-07-24 17:37 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, piastryyy-Re5JQEeQqe8AvxtiuMwx3w

Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 fs/cifs/cifsproto.h |    4 ++--
 fs/cifs/cifssmb.c   |   39 +++++++++++----------------------------
 fs/cifs/file.c      |   47 +++++++++--------------------------------------
 3 files changed, 22 insertions(+), 68 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index a2cf97b..77bcdba 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -516,8 +516,8 @@ struct cifs_writedata {
 	pid_t				pid;
 	unsigned int			bytes;
 	int				result;
-	void (*marshal_iov) (struct kvec *iov,
-			     struct cifs_writedata *wdata);
+	unsigned int			pagesz;
+	unsigned int			tailsz;
 	unsigned int			nr_pages;
 	struct page			*pages[1];
 };
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 7e51ec6..7826c78 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2048,11 +2048,11 @@ cifs_writev_callback(struct mid_q_entry *mid)
 int
 cifs_async_writev(struct cifs_writedata *wdata)
 {
-	int i, rc = -EACCES;
+	int rc = -EACCES;
 	WRITE_REQ *smb = NULL;
 	int wct;
 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-	struct kvec *iov = NULL;
+	struct kvec iov;
 	struct smb_rqst rqst = { };
 
 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -2069,15 +2069,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	if (rc)
 		goto async_writev_out;
 
-	/* 1 iov per page + 1 for header */
-	rqst.rq_nvec = wdata->nr_pages + 1;
-	iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
-	if (iov == NULL) {
-		rc = -ENOMEM;
-		goto async_writev_out;
-	}
-	rqst.rq_iov = iov;
-
 	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
 
@@ -2094,18 +2085,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
 
 	/* 4 for RFC1001 length + 1 for BCC */
-	iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
-	iov[0].iov_base = smb;
+	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
+	iov.iov_base = smb;
 
-	/*
-	 * This function should marshal up the page array into the kvec
-	 * array, reserving [0] for the header. It should kmap the pages
-	 * and set the iov_len properly for each one. It may also set
-	 * wdata->bytes too.
-	 */
-	cifs_kmap_lock();
-	wdata->marshal_iov(iov, wdata);
-	cifs_kmap_unlock();
+	rqst.rq_iov = &iov;
+	rqst.rq_nvec = 1;
+	rqst.rq_pages = wdata->pages;
+	rqst.rq_npages = wdata->nr_pages;
+	rqst.rq_pagesz = wdata->pagesz;
+	rqst.rq_tailsz = wdata->tailsz;
 
 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
 
@@ -2121,7 +2109,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
 				(struct smb_com_writex_req *)smb;
 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
 		put_bcc(wdata->bytes + 5, &smbw->hdr);
-		iov[0].iov_len += 4; /* pad bigger by four bytes */
+		iov.iov_len += 4; /* pad bigger by four bytes */
 	}
 
 	kref_get(&wdata->refcount);
@@ -2133,13 +2121,8 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	else
 		kref_put(&wdata->refcount, cifs_writedata_release);
 
-	/* send is done, unmap pages */
-	for (i = 0; i < wdata->nr_pages; i++)
-		kunmap(wdata->pages[i]);
-
 async_writev_out:
 	cifs_small_buf_release(smb);
-	kfree(iov);
 	return rc;
 }
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 1d5a268..88ddd1e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1708,27 +1708,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
 	return rc;
 }
 
-/*
- * Marshal up the iov array, reserving the first one for the header. Also,
- * set wdata->bytes.
- */
-static void
-cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
-{
-	int i;
-	struct inode *inode = wdata->cfile->dentry->d_inode;
-	loff_t size = i_size_read(inode);
-
-	/* marshal up the pages into iov array */
-	wdata->bytes = 0;
-	for (i = 0; i < wdata->nr_pages; i++) {
-		iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
-					(loff_t)PAGE_CACHE_SIZE);
-		iov[i + 1].iov_base = kmap(wdata->pages[i]);
-		wdata->bytes += iov[i + 1].iov_len;
-	}
-}
-
 static int cifs_writepages(struct address_space *mapping,
 			   struct writeback_control *wbc)
 {
@@ -1738,6 +1717,7 @@ static int cifs_writepages(struct address_space *mapping,
 	struct cifs_writedata *wdata;
 	struct page *page;
 	int rc = 0;
+	loff_t isize = i_size_read(mapping->host);
 
 	/*
 	 * If wsize is smaller than the page cache size, default to writing
@@ -1842,7 +1822,7 @@ retry:
 			 */
 			set_page_writeback(page);
 
-			if (page_offset(page) >= mapping->host->i_size) {
+			if (page_offset(page) >= isize) {
 				done = true;
 				unlock_page(page);
 				end_page_writeback(page);
@@ -1873,7 +1853,11 @@ retry:
 		wdata->sync_mode = wbc->sync_mode;
 		wdata->nr_pages = nr_pages;
 		wdata->offset = page_offset(wdata->pages[0]);
-		wdata->marshal_iov = cifs_writepages_marshal_iov;
+		wdata->pagesz = PAGE_CACHE_SIZE;
+		wdata->tailsz = min(isize - page_offset(wdata->pages[nr_pages - 1]),
+					(loff_t)PAGE_CACHE_SIZE);
+		wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
+					wdata->tailsz;
 
 		do {
 			if (wdata->cfile != NULL)
@@ -2162,20 +2146,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
 }
 
 static void
-cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
-{
-	int i;
-	size_t bytes = wdata->bytes;
-
-	/* marshal up the pages into iov array */
-	for (i = 0; i < wdata->nr_pages; i++) {
-		iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
-		iov[i + 1].iov_base = kmap(wdata->pages[i]);
-		bytes -= iov[i + 1].iov_len;
-	}
-}
-
-static void
 cifs_uncached_writev_complete(struct work_struct *work)
 {
 	int i;
@@ -2288,7 +2258,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 		wdata->cfile = cifsFileInfo_get(open_file);
 		wdata->pid = pid;
 		wdata->bytes = cur_len;
-		wdata->marshal_iov = cifs_uncached_marshal_iov;
+		wdata->pagesz = PAGE_SIZE;
+		wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
 		rc = cifs_uncached_retry_writev(wdata);
 		if (rc) {
 			kref_put(&wdata->refcount, cifs_writedata_release);
-- 
1.7.10.4

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

* Re: [PATCH 00/11] cifs: convert async write code to use less kmapping
       [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (10 preceding siblings ...)
  2012-07-18 17:59   ` [PATCH 11/11] cifs: add deprecation warning to sockopt=TCP_NODELAY option Jeff Layton
@ 2012-07-24 19:23   ` Pavel Shilovsky
  11 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-24 19:23 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> We currently have a problem with the async write code on CONFIG_HIGHMEM
> architectures. It uses *way* too much kmap space. Not only does this
> limit throughput by adding an artificial bottleneck, but it also can
> lead to deadlocks.
>
> Late in the 3.5 cycle, I sent some patches to limit the rsize and wsize
> on these arches as a temporary workaround. This patchset is a first pass
> at fixing this the right way, by teaching the low-level transport code
> how to deal with arrays of pages.
>
> Note that this is just a fix for the write codepaths. The read side will
> need a separate set of patches.
>
> The code seems to work correctly, and is probably suitable for the
> upcoming 3.6 merge window. This probably also has some non-trivial
> conflicts with Pavel's patches since I did not base this on top of his
> SMB2 work.
>
> Let me know what you plan to merge first for 3.6 and I can try to
> fix those up, or we can ask Pavel to rebase his code on top of this.
>
> Jeff Layton (11):
>   cifs: remove bogus reset of smb_buf_length in smb_send routines
>   cifs: rename cifs_sign_smb2 to cifs_sign_smbv
>   cifs: change signing routines to deal with smb_rqst structs
>   cifs: convert send code to use smb_rqst structs
>   cifs: cork the socket before a send and uncork it afterward
>   cifs: teach smb_send_rqst how to handle arrays of pages
>   cifs: teach signing routines how to deal with arrays of pages in a
>     smb_rqst
>   cifs: change cifs_call_async to use smb_rqst structs
>   cifs: convert async write code to pass in data via rq_pages array
>   cifs: remove the kmap size limit from wsize
>   cifs: add deprecation warning to sockopt=TCP_NODELAY option
>
>  fs/cifs/cifsencrypt.c |   39 +++++++--
>  fs/cifs/cifsproto.h   |   37 ++++++--
>  fs/cifs/cifssmb.c     |   53 ++++++------
>  fs/cifs/connect.c     |   10 ++-
>  fs/cifs/file.c        |   47 ++--------
>  fs/cifs/transport.c   |  227 ++++++++++++++++++++++++++++++++++++-------------
>  6 files changed, 264 insertions(+), 149 deletions(-)
>
> --
> 1.7.10.4
>
> --
> 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

I tested this patchset with cifs and smb2 code with cthon basic test
and it was ok - going to review patches tomorrow.

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 03/11] cifs: change signing routines to deal with smb_rqst structs
       [not found]     ` <1342634346-22818-4-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:04       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:04 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> We need a way to represent a call to be sent on the wire that does not
> require having all of the page data kmapped. Behold the smb_rqst struct.
> This new struct represents an array of kvecs immediately followed by an
> array of pages.
>
> Convert the signing routines to use these structs under the hood and
> turn the existing functions for this into wrappers around that. For now,
> we're just changing these functions to take different args. Later, we'll
> teach them how to deal with arrays of pages.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/cifsencrypt.c |   26 ++++++++++++++++++--------
>  fs/cifs/cifsproto.h   |   20 ++++++++++++++++++--
>  fs/cifs/cifssmb.c     |    6 ++++--
>  fs/cifs/transport.c   |    4 +++-
>  4 files changed, 43 insertions(+), 13 deletions(-)
>
> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
> index 6a0d741..e8953a0 100644
> --- a/fs/cifs/cifsencrypt.c
> +++ b/fs/cifs/cifsencrypt.c
> @@ -37,11 +37,13 @@
>   * the sequence number before this function is called. Also, this function
>   * should be called with the server->srv_mutex held.
>   */
> -static int cifs_calc_signature(const struct kvec *iov, int n_vec,
> +static int cifs_calc_signature(struct smb_rqst *rqst,
>                         struct TCP_Server_Info *server, char *signature)
>  {
>         int i;
>         int rc;
> +       struct kvec *iov = rqst->rq_iov;
> +       int n_vec = rqst->rq_nvec;
>
>         if (iov == NULL || signature == NULL || server == NULL)
>                 return -EINVAL;
> @@ -99,12 +101,12 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
>  }
>
>  /* must be called with server->srv_mutex held */
> -int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
> +int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
>                    __u32 *pexpected_response_sequence_number)
>  {
>         int rc = 0;
>         char smb_signature[20];
> -       struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
> +       struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
>
>         if ((cifs_pdu == NULL) || (server == NULL))
>                 return -EINVAL;
> @@ -125,7 +127,7 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
>         *pexpected_response_sequence_number = server->sequence_number++;
>         server->sequence_number++;
>
> -       rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
> +       rc = cifs_calc_signature(rqst, server, smb_signature);
>         if (rc)
>                 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
>         else
> @@ -134,6 +136,15 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
>         return rc;
>  }
>
> +int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
> +                  __u32 *pexpected_response_sequence)
> +{
> +       struct smb_rqst rqst = { .rq_iov = iov,
> +                                .rq_nvec = n_vec };
> +
> +       return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
> +}
> +
>  /* 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)
> @@ -147,14 +158,14 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
>                               pexpected_response_sequence_number);
>  }
>
> -int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
> +int cifs_verify_signature(struct smb_rqst *rqst,
>                           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;
> +       struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
>
>         if (cifs_pdu == NULL || server == NULL)
>                 return -EINVAL;
> @@ -186,8 +197,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
>         cifs_pdu->Signature.Sequence.Reserved = 0;
>
>         mutex_lock(&server->srv_mutex);
> -       rc = cifs_calc_signature(iov, nr_iov, server,
> -                                what_we_think_sig_should_be);
> +       rc = cifs_calc_signature(rqst, 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 b09aa22..b59e066 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -397,10 +397,26 @@ extern void sesInfoFree(struct cifs_ses *);
>  extern struct cifs_tcon *tconInfoAlloc(void);
>  extern void tconInfoFree(struct cifs_tcon *);
>
> -extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
> +/*
> + * A smb_rqst represents a complete request to be issued to a server. It's
> + * formed by a kvec array, followed by an array of pages. Page data is assumed
> + * to start at the beginning of the first page.
> + */
> +struct smb_rqst {
> +       struct kvec     *rq_iov;        /* array of kvecs */
> +       unsigned int    rq_nvec;        /* number of kvecs in array */
> +       struct page     **rq_pages;     /* pointer to array of page ptrs */
> +       unsigned int    rq_npages;      /* number pages in array */
> +       unsigned int    rq_pagesz;      /* page size to use */
> +       unsigned int    rq_tailsz;      /* length of last page */
> +};

Why you are adding new struct into cifsproto.h file? It seems like
cifsproto.h has only function prototypes but all structs are in
cifsglob.h. I suggest to add new structs into cifsglob.h.

> +
> +extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
> +                  __u32 *pexpected_response_sequence_number);
>  extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
>                           __u32 *);
> -extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
> +extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
> +extern int cifs_verify_signature(struct smb_rqst *rqst,
>                                  struct TCP_Server_Info *server,
>                                 __u32 expected_sequence_number);
>  extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 1a05ab0..c010c279 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -1562,6 +1562,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
>         struct cifs_readdata *rdata = mid->callback_data;
>         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
>         struct TCP_Server_Info *server = tcon->ses->server;
> +       struct smb_rqst rqst = { .rq_iov = rdata->iov,
> +                                .rq_nvec = rdata->nr_iov };
>
>         cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
>                 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
> @@ -1571,8 +1573,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
>                 /* result already set, check signature */
>                 if (server->sec_mode &
>                     (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
> -                       if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
> -                                         server, mid->sequence_number + 1))
> +                       if (cifs_verify_signature(&rqst, server,
> +                                                 mid->sequence_number + 1))
>                                 cERROR(1, "Unexpected SMB signature");
>                 }
>                 /* FIXME: should this be counted toward the initiating task? */
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 462130d..531da42 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -498,11 +498,13 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
>         /* convert the length into a more usable form */
>         if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
>                 struct kvec iov;
> +               struct smb_rqst rqst = { .rq_iov = &iov,
> +                                        .rq_nvec = 1 };
>
>                 iov.iov_base = mid->resp_buf;
>                 iov.iov_len = len;
>                 /* FIXME: add code to kill session */
> -               if (cifs_verify_signature(&iov, 1, server,
> +               if (cifs_verify_signature(&rqst, server,
>                                           mid->sequence_number + 1) != 0)
>                         cERROR(1, "Unexpected SMB signature");
>         }
> --
> 1.7.10.4
>
> --
> 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

Other than the comment above it seems good.

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 04/11] cifs: convert send code to use smb_rqst structs
       [not found]     ` <1342634346-22818-5-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:23       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:23 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Again, just a change in the arguments and some function renaming here.
> In later patches, we'll change this code to deal with page arrays.
>
> In this patch, we add a new smb_send_rqst wrapper and have smb_sendv
> call that. Then we move most of the existing smb_sendv code into a new
> function -- smb_send_kvec. This seems a little redundant, but later
> we'll flesh this out to deal with arrays of pages.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/transport.c |  135 ++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 90 insertions(+), 45 deletions(-)
>
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 531da42..5a1d817 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -120,18 +120,29 @@ delete_mid(struct mid_q_entry *mid)
>         DeleteMidQEntry(mid);
>  }
>
> +/*
> + * smb_send_kvec - send an array of kvecs to the server
> + * @server:    Server to send the data to
> + * @iov:       Pointer to array of kvecs
> + * @n_vec:     length of kvec array
> + * @sent:      amount of data sent on socket is stored here
> + *
> + * Our basic "send data to server" function. Should be called with srv_mutex
> + * held. The caller is responsible for handling the results.
> + */
>  static int
> -smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
> +smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
> +               size_t *sent)
>  {
>         int rc = 0;
>         int i = 0;
>         struct msghdr smb_msg;
> -       unsigned int len = iov[0].iov_len;
> -       unsigned int total_len;
> -       int first_vec = 0;
> -       unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
> +       unsigned int remaining;
> +       size_t first_vec = 0;
>         struct socket *ssocket = server->ssocket;
>
> +       *sent = 0;
> +
>         if (ssocket == NULL)
>                 return -ENOTSOCK; /* BB eventually add reconnect code here */
>
> @@ -144,56 +155,60 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>         else
>                 smb_msg.msg_flags = MSG_NOSIGNAL;
>
> -       total_len = 0;
> +       remaining = 0;
>         for (i = 0; i < n_vec; i++)
> -               total_len += iov[i].iov_len;
> -
> -       cFYI(1, "Sending smb:  total_len %d", total_len);
> -       dump_smb(iov[0].iov_base, len);
> +               remaining += iov[i].iov_len;
>
>         i = 0;
> -       while (total_len) {
> +       while (remaining) {
> +               /*
> +                * If blocking send, we try 3 times, since each can block
> +                * for 5 seconds. For nonblocking  we have to try more
> +                * but wait increasing amounts of time allowing time for
> +                * socket to clear.  The overall time we wait in either
> +                * case to send on the socket is about 15 seconds.
> +                * Similarly we wait for 15 seconds for a response from
> +                * the server in SendReceive[2] for the server to send
> +                * a response back for most types of requests (except
> +                * SMB Write past end of file which can be slow, and
> +                * blocking lock operations). NFS waits slightly longer
> +                * than CIFS, but this can make it take longer for
> +                * nonresponsive servers to be detected and 15 seconds
> +                * is more than enough time for modern networks to
> +                * send a packet.  In most cases if we fail to send
> +                * after the retries we will kill the socket and
> +                * reconnect which may clear the network problem.
> +                */
>                 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
> -                                   n_vec - first_vec, total_len);
> -               if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
> +                                   n_vec - first_vec, remaining);
> +               if (rc == -ENOSPC || rc == -EAGAIN) {
>                         i++;
> -                       /*
> -                        * If blocking send we try 3 times, since each can block
> -                        * for 5 seconds. For nonblocking  we have to try more
> -                        * but wait increasing amounts of time allowing time for
> -                        * socket to clear.  The overall time we wait in either
> -                        * case to send on the socket is about 15 seconds.
> -                        * Similarly we wait for 15 seconds for a response from
> -                        * the server in SendReceive[2] for the server to send
> -                        * a response back for most types of requests (except
> -                        * SMB Write past end of file which can be slow, and
> -                        * blocking lock operations). NFS waits slightly longer
> -                        * than CIFS, but this can make it take longer for
> -                        * nonresponsive servers to be detected and 15 seconds
> -                        * is more than enough time for modern networks to
> -                        * send a packet.  In most cases if we fail to send
> -                        * after the retries we will kill the socket and
> -                        * reconnect which may clear the network problem.
> -                        */
> -                       if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
> -                               cERROR(1, "sends on sock %p stuck for 15 seconds",
> -                                   ssocket);
> +                       if (i >= 14 || (!server->noblocksnd && (i > 2))) {
> +                               cERROR(1, "sends on sock %p stuck for 15 "
> +                                         "seconds", ssocket);
>                                 rc = -EAGAIN;
>                                 break;
>                         }
>                         msleep(1 << i);
>                         continue;
>                 }
> +
>                 if (rc < 0)
>                         break;
>
> -               if (rc == total_len) {
> -                       total_len = 0;
> +               /* send was at least partially successful */
> +               *sent += rc;
> +
> +               if (rc == remaining) {
> +                       remaining = 0;
>                         break;
> -               } else if (rc > total_len) {
> -                       cERROR(1, "sent %d requested %d", rc, total_len);
> +               }
> +
> +               if (rc > remaining) {
> +                       cERROR(1, "sent %d requested %d", rc, remaining);
>                         break;
>                 }
> +
>                 if (rc == 0) {
>                         /* should never happen, letting socket clear before
>                            retrying is our only obvious option here */
> @@ -201,7 +216,9 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>                         msleep(500);
>                         continue;
>                 }
> -               total_len -= rc;
> +
> +               remaining -= rc;
> +
>                 /* the line below resets i */
>                 for (i = first_vec; i < n_vec; i++) {
>                         if (iov[i].iov_len) {
> @@ -216,16 +233,35 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>                                 }
>                         }
>                 }
> +
>                 i = 0; /* in case we get ENOSPC on the next send */
> +               rc = 0;
>         }
> +       return rc;
> +}
> +
> +static int
> +smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
> +{
> +       int rc;
> +       struct kvec *iov = rqst->rq_iov;
> +       int n_vec = rqst->rq_nvec;
> +       unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
> +       size_t total_len;
> +
> +       cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
> +       dump_smb(iov[0].iov_base, iov[0].iov_len);
> +
> +       rc = smb_send_kvec(server, iov, n_vec, &total_len);
>
>         if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
> -               cFYI(1, "partial send (%d remaining), terminating session",
> -                       total_len);
> -               /* If we have only sent part of an SMB then the next SMB
> -                  could be taken as the remainder of this one.  We need
> -                  to kill the socket so the server throws away the partial
> -                  SMB */
> +               cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
> +                       "session", smb_buf_length + 4, total_len);
> +               /*
> +                * If we have only sent part of an SMB then the next SMB could
> +                * be taken as the remainder of this one. We need to kill the
> +                * socket so the server throws away the partial SMB
> +                */
>                 server->tcpStatus = CifsNeedReconnect;
>         }
>
> @@ -237,6 +273,15 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>         return rc;
>  }
>
> +static int
> +smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
> +{
> +       struct smb_rqst rqst = { .rq_iov = iov,
> +                                .rq_nvec = n_vec };
> +
> +       return smb_send_rqst(server, &rqst);
> +}
> +
>  int
>  smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
>          unsigned int smb_buf_length)
> --
> 1.7.10.4
>
> --
> 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

Looks good.

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 05/11] cifs: cork the socket before a send and uncork it afterward
       [not found]     ` <1342634346-22818-6-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:28       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:28 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> We want to send SMBs as "atomically" as possible. Prior to sending any
> data on the socket, cork it to make sure that no non-full frames go
> out. Afterward, uncork it to make sure all of the data gets pushed out
> to the wire.
>
> Note that this more or less renders the socket=TCP_NODELAY mount option
> obsolete. When TCP_CORK and TCP_NODELAY are used on the same socket,
> TCP_NODELAY is essentially ignored.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/connect.c   |    4 ++++
>  fs/cifs/transport.c |   12 ++++++++++++
>  2 files changed, 16 insertions(+)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index e8c3e6b..99ca139 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -1830,6 +1830,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
>                         if (string == NULL)
>                                 goto out_nomem;
>
> +                       /*
> +                        * FIXME: since we now cork/uncork the socket while
> +                        *        sending, should we deprecate this option?
> +                        */
>                         if (strnicmp(string, "TCP_NODELAY", 11) == 0)
>                                 vol->sockopt_tcp_nodelay = 1;
>                         break;
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 5a1d817..af56e91 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -27,6 +27,7 @@
>  #include <linux/net.h>
>  #include <linux/delay.h>
>  #include <linux/freezer.h>
> +#include <linux/tcp.h>
>  #include <asm/uaccess.h>
>  #include <asm/processor.h>
>  #include <linux/mempool.h>
> @@ -248,12 +249,23 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
>         int n_vec = rqst->rq_nvec;
>         unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
>         size_t total_len;
> +       struct socket *ssocket = server->ssocket;
> +       int val = 1;
>
>         cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
>         dump_smb(iov[0].iov_base, iov[0].iov_len);
>
> +       /* cork the socket */
> +       kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
> +                               (char *)&val, sizeof(val));
> +
>         rc = smb_send_kvec(server, iov, n_vec, &total_len);
>
> +       /* uncork it */
> +       val = 0;
> +       kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
> +                               (char *)&val, sizeof(val));
> +
>         if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
>                 cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
>                         "session", smb_buf_length + 4, total_len);
> --
> 1.7.10.4
>
> --
> 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

Acked-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 06/11] cifs: teach smb_send_rqst how to handle arrays of pages
       [not found]     ` <1342634346-22818-7-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:28       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:28 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Add code that allows smb_send_rqst to send an array of pages after the
> initial kvec array has been sent. For now, we simply kmap the page
> array and send it using the standard smb_send_kvec function. Eventually,
> we may want to convert this code to use kernel_sendpage under the hood
> and avoid the kmap altogether for the page data.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/transport.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 54 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index af56e91..006c3fb 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -28,6 +28,7 @@
>  #include <linux/delay.h>
>  #include <linux/freezer.h>
>  #include <linux/tcp.h>
> +#include <linux/highmem.h>
>  #include <asm/uaccess.h>
>  #include <asm/processor.h>
>  #include <linux/mempool.h>
> @@ -241,6 +242,38 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
>         return rc;
>  }
>
> +/**
> + * rqst_page_to_kvec - Turn a slot in the smb_rqst page array into a kvec
> + * @rqst: pointer to smb_rqst
> + * @idx: index into the array of the page
> + * @iov: pointer to struct kvec that will hold the result
> + *
> + * Helper function to convert a slot in the rqst->rq_pages array into a kvec.
> + * The page will be kmapped and the address placed into iov_base. The length
> + * will then be adjusted according to the ptailoff.
> + */
> +static void
> +cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
> +                       struct kvec *iov)
> +{
> +       /*
> +        * FIXME: We could avoid this kmap altogether if we used
> +        * kernel_sendpage instead of kernel_sendmsg. That will only
> +        * work if signing is disabled though as sendpage inlines the
> +        * page directly into the fraglist. If userspace modifies the
> +        * page after we calculate the signature, then the server will
> +        * reject it and may break the connection. kernel_sendmsg does
> +        * an extra copy of the data and avoids that issue.
> +        */
> +       iov->iov_base = kmap(rqst->rq_pages[idx]);
> +
> +       /* if last page, don't send beyond this offset into page */
> +       if (idx == (rqst->rq_npages - 1))
> +               iov->iov_len = rqst->rq_tailsz;
> +       else
> +               iov->iov_len = rqst->rq_pagesz;
> +}
> +
>  static int
>  smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
>  {
> @@ -248,7 +281,8 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
>         struct kvec *iov = rqst->rq_iov;
>         int n_vec = rqst->rq_nvec;
>         unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
> -       size_t total_len;
> +       unsigned int i;
> +       size_t total_len = 0, sent;
>         struct socket *ssocket = server->ssocket;
>         int val = 1;
>
> @@ -259,8 +293,26 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
>         kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
>                                 (char *)&val, sizeof(val));
>
> -       rc = smb_send_kvec(server, iov, n_vec, &total_len);
> +       rc = smb_send_kvec(server, iov, n_vec, &sent);
> +       if (rc < 0)
> +               goto uncork;
> +
> +       total_len += sent;
> +
> +       /* now walk the page array and send each page in it */
> +       for (i = 0; i < rqst->rq_npages; i++) {
> +               struct kvec p_iov;
> +
> +               cifs_rqst_page_to_kvec(rqst, i, &p_iov);
> +               rc = smb_send_kvec(server, &p_iov, 1, &sent);
> +               kunmap(rqst->rq_pages[i]);
> +               if (rc < 0)
> +                       break;
> +
> +               total_len += sent;
> +       }
>
> +uncork:
>         /* uncork it */
>         val = 0;
>         kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 07/11] cifs: teach signing routines how to deal with arrays of pages in a smb_rqst
       [not found]     ` <1342634346-22818-8-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:29       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:29 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Use the smb_send_rqst helper function to kmap each page in the array
> and update the hash for that chunk.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/cifsencrypt.c |   11 +++++++++++
>  fs/cifs/cifsproto.h   |    3 +++
>  fs/cifs/transport.c   |    2 +-
>  3 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
> index e8953a0..511d1ae 100644
> --- a/fs/cifs/cifsencrypt.c
> +++ b/fs/cifs/cifsencrypt.c
> @@ -29,6 +29,7 @@
>  #include "ntlmssp.h"
>  #include <linux/ctype.h>
>  #include <linux/random.h>
> +#include <linux/highmem.h>
>
>  /*
>   * Calculate and return the CIFS signature based on the mac key and SMB PDU.
> @@ -93,6 +94,16 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
>                 }
>         }
>
> +       /* now hash over the rq_pages array */
> +       for (i = 0; i < rqst->rq_npages; i++) {
> +               struct kvec p_iov;
> +
> +               cifs_rqst_page_to_kvec(rqst, i, &p_iov);
> +               crypto_shash_update(&server->secmech.sdescmd5->shash,
> +                                       p_iov.iov_base, p_iov.iov_len);
> +               kunmap(rqst->rq_pages[i]);
> +       }
> +
>         rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
>         if (rc)
>                 cERROR(1, "%s: Could not generate md5 hash", __func__);
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index b59e066..b2daad4 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -24,6 +24,7 @@
>
>  struct statfs;
>  struct smb_vol;
> +struct smb_rqst;
>
>  /*
>   *****************************************************************
> @@ -35,6 +36,8 @@ extern struct smb_hdr *cifs_buf_get(void);
>  extern void cifs_buf_release(void *);
>  extern struct smb_hdr *cifs_small_buf_get(void);
>  extern void cifs_small_buf_release(void *);
> +extern void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
> +                                       struct kvec *iov);
>  extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
>                         unsigned int /* length */);
>  extern unsigned int _GetXid(void);
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 006c3fb..8e689d1 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -252,7 +252,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
>   * The page will be kmapped and the address placed into iov_base. The length
>   * will then be adjusted according to the ptailoff.
>   */
> -static void
> +void
>  cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
>                         struct kvec *iov)
>  {
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 08/11] cifs: change cifs_call_async to use smb_rqst structs
       [not found]     ` <1342634346-22818-9-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:30       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:30 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> For now, none of the callers populate rq_pages. That will be done for
> writes in a later patch.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/cifsproto.h |    8 ++++----
>  fs/cifs/cifssmb.c   |   20 +++++++++++++-------
>  fs/cifs/transport.c |   18 +++++++++---------
>  3 files changed, 26 insertions(+), 20 deletions(-)
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index b2daad4..dbb9c61 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -71,10 +71,10 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
>  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_receive_t *receive,
> -                          mid_callback_t *callback, void *cbdata,
> -                          bool ignore_pend);
> +extern int cifs_call_async(struct TCP_Server_Info *server,
> +                       struct smb_rqst *rqst, mid_receive_t *receive,
> +                       mid_callback_t *callback, void *cbdata,
> +                       bool ignore_pend);

This will cause merge conflicts with current Steve's for-next branch -
needs a respin.

>  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 c010c279..727f35e 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -753,6 +753,8 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
>         ECHO_REQ *smb;
>         int rc = 0;
>         struct kvec iov;
> +       struct smb_rqst rqst = { .rq_iov = &iov,
> +                                .rq_nvec = 1 };
>
>         cFYI(1, "In echo request");
>
> @@ -770,7 +772,7 @@ 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, NULL, cifs_echo_callback,
> +       rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
>                              server, true);
>         if (rc)
>                 cFYI(1, "Echo request failed: %d", rc);
> @@ -1602,6 +1604,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
>         READ_REQ *smb = NULL;
>         int wct;
>         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
> +       struct smb_rqst rqst = { .rq_iov = rdata->iov,
> +                                .rq_nvec = 1 };
>
>         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
>                 rdata->offset, rdata->bytes);
> @@ -1645,9 +1649,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
>         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
>
>         kref_get(&rdata->refcount);
> -       rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
> -                            cifs_readv_receive, cifs_readv_callback,
> -                            rdata, false);
> +       rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
> +                            cifs_readv_callback, rdata, false);
>
>         if (rc == 0)
>                 cifs_stats_inc(&tcon->num_reads);
> @@ -2050,6 +2053,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
>         int wct;
>         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
>         struct kvec *iov = NULL;
> +       struct smb_rqst rqst = { };
>
>         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
>                 wct = 14;
> @@ -2066,11 +2070,13 @@ cifs_async_writev(struct cifs_writedata *wdata)
>                 goto async_writev_out;
>
>         /* 1 iov per page + 1 for header */
> -       iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
> +       rqst.rq_nvec = wdata->nr_pages + 1;
> +       iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
>         if (iov == NULL) {
>                 rc = -ENOMEM;
>                 goto async_writev_out;
>         }
> +       rqst.rq_iov = iov;
>
>         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
>         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
> @@ -2119,8 +2125,8 @@ cifs_async_writev(struct cifs_writedata *wdata)
>         }
>
>         kref_get(&wdata->refcount);
> -       rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
> -                            NULL, cifs_writev_callback, wdata, false);
> +       rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
> +                               cifs_writev_callback, wdata, false);
>
>         if (rc == 0)
>                 cifs_stats_inc(&tcon->num_writes);
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 8e689d1..83a1489 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -455,11 +455,11 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
>  }
>
>  static int
> -cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
> -                        unsigned int nvec, struct mid_q_entry **ret_mid)
> +cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst,
> +                        struct mid_q_entry **ret_mid)
>  {
>         int rc;
> -       struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
> +       struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
>         struct mid_q_entry *mid;
>
>         /* enable signing if server requires it */
> @@ -475,7 +475,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
>         list_add_tail(&mid->qhead, &server->pending_mid_q);
>         spin_unlock(&GlobalMid_Lock);
>
> -       rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
> +       rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
>         if (rc)
>                 delete_mid(mid);
>         *ret_mid = mid;
> @@ -487,9 +487,9 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
>   * the result. Caller is responsible for dealing with timeouts.
>   */
>  int
> -cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
> -               unsigned int nvec, mid_receive_t *receive,
> -               mid_callback_t *callback, void *cbdata, bool ignore_pend)
> +cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
> +               mid_receive_t *receive, mid_callback_t *callback,
> +               void *cbdata, bool ignore_pend)
>  {
>         int rc;
>         struct mid_q_entry *mid;
> @@ -499,7 +499,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
>                 return rc;
>
>         mutex_lock(&server->srv_mutex);
> -       rc = cifs_setup_async_request(server, iov, nvec, &mid);
> +       rc = cifs_setup_async_request(server, rqst, &mid);
>         if (rc) {
>                 mutex_unlock(&server->srv_mutex);
>                 add_credits(server, 1);
> @@ -513,7 +513,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
>         mid->mid_state = MID_REQUEST_SUBMITTED;
>
>         cifs_in_send_inc(server);
> -       rc = smb_sendv(server, iov, nvec);
> +       rc = smb_send_rqst(server, rqst);
>         cifs_in_send_dec(server);
>         cifs_save_when_sent(mid);
>         mutex_unlock(&server->srv_mutex);
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 10/11] cifs: remove the kmap size limit from wsize
       [not found]     ` <1342634346-22818-11-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:31       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:31 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Now that we're not kmapping so much at once, there's no need to cap
> the wsize at the amount that can be simultaneously kmapped.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/connect.c |    3 ---
>  1 file changed, 3 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 99ca139..303be53 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -3491,9 +3491,6 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
>                 wsize = min_t(unsigned int, wsize,
>                                 server->maxBuf - sizeof(WRITE_REQ) + 4);
>
> -       /* limit to the amount that we can kmap at once */
> -       wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
> -
>         /* hard limit of CIFS_MAX_WSIZE */
>         wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
>
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 11/11] cifs: add deprecation warning to sockopt=TCP_NODELAY option
       [not found]     ` <1342634346-22818-12-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:31       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:31 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Now that we're using TCP_CORK on the socket, there's no value in
> continuting to support this option. Schedule it for removal in 3.8.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/connect.c |   11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 303be53..29d9716 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -1830,12 +1830,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
>                         if (string == NULL)
>                                 goto out_nomem;
>
> -                       /*
> -                        * FIXME: since we now cork/uncork the socket while
> -                        *        sending, should we deprecate this option?
> -                        */
> -                       if (strnicmp(string, "TCP_NODELAY", 11) == 0)
> +                       if (strnicmp(string, "TCP_NODELAY", 11) == 0) {
> +                               printk(KERN_WARNING, "CIFS: the "
> +                                       "sockopt=TCP_NODELAY option has been "
> +                                       "deprecated and will be removed "
> +                                       "in 3.8\n");
>                                 vol->sockopt_tcp_nodelay = 1;
> +                       }
>                         break;
>                 case Opt_netbiosname:
>                         string = match_strdup(args);
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 01/11] cifs: remove bogus reset of smb_buf_length in smb_send routines
       [not found]     ` <1342634346-22818-2-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:34       ` Pavel Shilovsky
       [not found]         ` <CAKywueSdajZYQoNoBnUsPgm2DbH1FscJ=fiMn5F7Pf0ZV2qxTA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:34 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> There's a comment here about how we don't want to modify this length,
> but nothing in this function actually does.
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/transport.c |    4 ----
>  1 file changed, 4 deletions(-)
>
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 3097ee5..fa51913 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -126,7 +126,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>         int rc = 0;
>         int i = 0;
>         struct msghdr smb_msg;
> -       __be32 *buf_len = (__be32 *)(iov[0].iov_base);
>         unsigned int len = iov[0].iov_len;
>         unsigned int total_len;
>         int first_vec = 0;
> @@ -235,9 +234,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>         else
>                 rc = 0;
>
> -       /* Don't want to modify the buffer as a side effect of this call. */
> -       *buf_len = cpu_to_be32(smb_buf_length);
> -
>         return rc;
>  }
>
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 01/11] cifs: remove bogus reset of smb_buf_length in smb_send routines
       [not found]         ` <CAKywueSdajZYQoNoBnUsPgm2DbH1FscJ=fiMn5F7Pf0ZV2qxTA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-07-25 12:34           ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:34 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/25 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> 2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>> There's a comment here about how we don't want to modify this length,
>> but nothing in this function actually does.
>>
>> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> ---
>>  fs/cifs/transport.c |    4 ----
>>  1 file changed, 4 deletions(-)
>>
>> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
>> index 3097ee5..fa51913 100644
>> --- a/fs/cifs/transport.c
>> +++ b/fs/cifs/transport.c
>> @@ -126,7 +126,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>>         int rc = 0;
>>         int i = 0;
>>         struct msghdr smb_msg;
>> -       __be32 *buf_len = (__be32 *)(iov[0].iov_base);
>>         unsigned int len = iov[0].iov_len;
>>         unsigned int total_len;
>>         int first_vec = 0;
>> @@ -235,9 +234,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
>>         else
>>                 rc = 0;
>>
>> -       /* Don't want to modify the buffer as a side effect of this call. */
>> -       *buf_len = cpu_to_be32(smb_buf_length);
>> -
>>         return rc;
>>  }
>>
>> --
>> 1.7.10.4
>>
>> --
>> 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
>
> Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org

(sorry for the typo)

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

* Re: [PATCH 02/11] cifs: rename cifs_sign_smb2 to cifs_sign_smbv
       [not found]     ` <1342634346-22818-3-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2012-07-25 12:34       ` Pavel Shilovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Pavel Shilovsky @ 2012-07-25 12:34 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/7/18 Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> "smb2" makes me think of the SMB2.x protocol, which isn't at all what
> this function is for...
>
> Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/cifs/cifsencrypt.c |    4 ++--
>  fs/cifs/cifsproto.h   |    2 +-
>  fs/cifs/transport.c   |    4 ++--
>  3 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
> index db768cb..6a0d741 100644
> --- a/fs/cifs/cifsencrypt.c
> +++ b/fs/cifs/cifsencrypt.c
> @@ -99,7 +99,7 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
>  }
>
>  /* must be called with server->srv_mutex held */
> -int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
> +int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
>                    __u32 *pexpected_response_sequence_number)
>  {
>         int rc = 0;
> @@ -143,7 +143,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
>         iov.iov_base = cifs_pdu;
>         iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
>
> -       return cifs_sign_smb2(&iov, 1, server,
> +       return cifs_sign_smbv(&iov, 1, server,
>                               pexpected_response_sequence_number);
>  }
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 0a6cbfe..b09aa22 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -398,7 +398,7 @@ extern struct cifs_tcon *tconInfoAlloc(void);
>  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 *,
> +extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
>                           __u32 *);
>  extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
>                                  struct TCP_Server_Info *server,
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index fa51913..462130d 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -366,7 +366,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
>         list_add_tail(&mid->qhead, &server->pending_mid_q);
>         spin_unlock(&GlobalMid_Lock);
>
> -       rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
> +       rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
>         if (rc)
>                 delete_mid(mid);
>         *ret_mid = mid;
> @@ -522,7 +522,7 @@ cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
>         rc = allocate_mid(ses, hdr, &mid);
>         if (rc)
>                 return rc;
> -       rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number);
> +       rc = cifs_sign_smbv(iov, nvec, ses->server, &mid->sequence_number);
>         if (rc)
>                 delete_mid(mid);
>         *ret_mid = mid;
> --
> 1.7.10.4
>
> --
> 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

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

-- 
Best regards,
Pavel Shilovsky.

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

end of thread, other threads:[~2012-07-25 12:34 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-18 17:58 [PATCH 00/11] cifs: convert async write code to use less kmapping Jeff Layton
     [not found] ` <1342634346-22818-1-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-18 17:58   ` [PATCH 01/11] cifs: remove bogus reset of smb_buf_length in smb_send routines Jeff Layton
     [not found]     ` <1342634346-22818-2-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:34       ` Pavel Shilovsky
     [not found]         ` <CAKywueSdajZYQoNoBnUsPgm2DbH1FscJ=fiMn5F7Pf0ZV2qxTA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-07-25 12:34           ` Pavel Shilovsky
2012-07-18 17:58   ` [PATCH 02/11] cifs: rename cifs_sign_smb2 to cifs_sign_smbv Jeff Layton
     [not found]     ` <1342634346-22818-3-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:34       ` Pavel Shilovsky
2012-07-18 17:58   ` [PATCH 03/11] cifs: change signing routines to deal with smb_rqst structs Jeff Layton
     [not found]     ` <1342634346-22818-4-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:04       ` Pavel Shilovsky
2012-07-18 17:58   ` [PATCH 04/11] cifs: convert send code to use " Jeff Layton
     [not found]     ` <1342634346-22818-5-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:23       ` Pavel Shilovsky
2012-07-18 17:59   ` [PATCH 05/11] cifs: cork the socket before a send and uncork it afterward Jeff Layton
     [not found]     ` <1342634346-22818-6-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:28       ` Pavel Shilovsky
2012-07-18 17:59   ` [PATCH 06/11] cifs: teach smb_send_rqst how to handle arrays of pages Jeff Layton
     [not found]     ` <1342634346-22818-7-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:28       ` Pavel Shilovsky
2012-07-18 17:59   ` [PATCH 07/11] cifs: teach signing routines how to deal with arrays of pages in a smb_rqst Jeff Layton
     [not found]     ` <1342634346-22818-8-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:29       ` Pavel Shilovsky
2012-07-18 17:59   ` [PATCH 08/11] cifs: change cifs_call_async to use smb_rqst structs Jeff Layton
     [not found]     ` <1342634346-22818-9-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:30       ` Pavel Shilovsky
2012-07-18 17:59   ` [PATCH 09/11] cifs: convert async write code to pass in data via rq_pages array Jeff Layton
     [not found]     ` <1342634346-22818-10-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-24  9:44       ` Pavel Shilovsky
     [not found]         ` <CAKywueTO3OCTV8M4Lo1kSpfZjyHDPDxRZthE-URkr=5=ow-Z2g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-07-24 10:19           ` Jeff Layton
2012-07-24 17:37           ` [PATCH v2 " Jeff Layton
2012-07-18 17:59   ` [PATCH 10/11] cifs: remove the kmap size limit from wsize Jeff Layton
     [not found]     ` <1342634346-22818-11-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:31       ` Pavel Shilovsky
2012-07-18 17:59   ` [PATCH 11/11] cifs: add deprecation warning to sockopt=TCP_NODELAY option Jeff Layton
     [not found]     ` <1342634346-22818-12-git-send-email-jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2012-07-25 12:31       ` Pavel Shilovsky
2012-07-24 19:23   ` [PATCH 00/11] cifs: convert async write code to use less kmapping Pavel Shilovsky

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.