[PATCH 06/50] CIFS: Add SMB2 credits support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Steve French <sfrench@xxxxxxxxxx>

Convert wait_for_free_request to wait on available credits
for SMB2 servers and decrement a credit number for every call.
Increment the credit number in smb2_sendrcv2 with every response
got from the server.

Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
---
 fs/cifs/cifsglob.h      |    1 +
 fs/cifs/cifsproto.h     |    2 +-
 fs/cifs/smb2transport.c |    6 ++++++
 fs/cifs/transport.c     |   20 ++++++++++++++++++--
 4 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index bb2af48..e5f0b86 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -318,6 +318,7 @@ struct TCP_Server_Info {
 	atomic_t num_waiters;   /* blocked waiting to get in sendrecv */
 #endif
 #ifdef CONFIG_CIFS_SMB2
+	atomic_t credits; /* send no more simultaneous requests than this */
 	__u64 current_smb2_mid;         /* multiplex id - rotating counter */
 #endif
 };
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d1e30d9..b6c784b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsproto.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002,2008
+ *   Copyright (c) International Business Machines  Corp., 2002,2011
  *   Author(s): Steve French (sfrench@xxxxxxxxxx)
  *
  *   This library is free software; you can redistribute it and/or modify
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index d7f1c05..b5702f3 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -148,6 +148,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
 	unsigned int receive_len;
 	struct mid_q_entry *midQ;
 	struct smb2_hdr *buf = iov[0].iov_base;
+	unsigned int credits = 1;
 
 	if (status)
 		*status = STATUS_SUCCESS;
@@ -186,6 +187,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
 	if (rc) {
 		mutex_unlock(&ses->server->srv_mutex);
 		cifs_small_buf_release(buf);
+		atomic_inc(&ses->server->credits);
 		wake_up(&ses->server->request_q);
 		return rc;
 	}
@@ -222,6 +224,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
 			midQ->callback = cifs_delete_mid;
 			spin_unlock(&GlobalMid_Lock);
 			cifs_small_buf_release(buf);
+			atomic_inc(&ses->server->credits);
 			wake_up(&ses->server->request_q);
 			return rc;
 		}
@@ -232,6 +235,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
 
 	rc = cifs_sync_mid_result(midQ, ses->server);
 	if (rc) {
+		atomic_inc(&ses->server->credits);
 		wake_up(&ses->server->request_q);
 		return rc;
 	}
@@ -271,7 +275,9 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
 		/* mark it so buf will not be freed by free_smb2mid */
 		midQ->resp_buf = NULL;
 
+	credits = le16_to_cpu(buf->CreditRequest);
 out:
+	atomic_add(credits, &ses->server->credits);
 	cifs_delete_mid(midQ);
 	wake_up(&ses->server->request_q);
 	return rc;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f7ac3f0..4414df8 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -287,7 +287,8 @@ cifs_wait_for_free_request(struct TCP_Server_Info *server, const int long_op)
 
 	spin_lock(&GlobalMid_Lock);
 	while (1) {
-		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
+		if ((server->is_smb2 == false) &&
+		    atomic_read(&server->inFlight) >= cifs_max_pending) {
 			spin_unlock(&GlobalMid_Lock);
 			cifs_num_waiters_inc(server);
 			wait_event(server->request_q,
@@ -295,6 +296,16 @@ cifs_wait_for_free_request(struct TCP_Server_Info *server, const int long_op)
 				     < cifs_max_pending);
 			cifs_num_waiters_dec(server);
 			spin_lock(&GlobalMid_Lock);
+#ifdef CONFIG_CIFS_SMB2
+		} else if (server->is_smb2 &&
+			  (atomic_read(&server->credits) < 1)) {
+			spin_unlock(&GlobalMid_Lock);
+			cifs_num_waiters_inc(server);
+			wait_event(server->request_q,
+				   atomic_read(&server->credits) > 0);
+			cifs_num_waiters_dec(server);
+			spin_lock(&GlobalMid_Lock);
+#endif /* CONFIG_CIFS_SMB2 */
 		} else {
 			if (server->tcpStatus == CifsExiting) {
 				spin_unlock(&GlobalMid_Lock);
@@ -305,8 +316,13 @@ cifs_wait_for_free_request(struct TCP_Server_Info *server, const int long_op)
 			   as they are allowed to block on server */
 
 			/* update # of requests on the wire to server */
-			if (long_op != CIFS_BLOCKING_OP)
+			if (server->is_smb2 == false &&
+			    long_op != CIFS_BLOCKING_OP)
 				atomic_inc(&server->inFlight);
+#ifdef CONFIG_CIFS_SMB2
+			else if (server->is_smb2)
+				atomic_dec(&server->credits);
+#endif
 			spin_unlock(&GlobalMid_Lock);
 			break;
 		}
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux