[PATCH 2/3] cifs: stop waiting for credits if there are no more requests in flight

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

 



A compound request will wait for credits if free credits are not enough
now but there are in flight requests which might bring back some credits
to meet our needs in the near future.

But if the in-flight requests don't bring back enough credits, the
compound request will continue to wait unnecessarily until it times out
(60s now).

So add a helper has_credits_or_insufficient() to check if we should stop
waiting for credits in the loop to return faster.

Signed-off-by: Winston Wen <wentao@xxxxxxxxxxxxx>
---
 fs/smb/client/cifsglob.h  | 13 +++++++++++++
 fs/smb/client/transport.c | 16 +++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index cb38c29b9a73..43d0a675b543 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -800,6 +800,19 @@ has_credits(struct TCP_Server_Info *server, int *credits, int num_credits)
 	return num >= num_credits;
 }
 
+static inline bool
+has_credits_or_insufficient(struct TCP_Server_Info *server, int *credits, int num_credits)
+{
+	int scredits;
+	int in_flight;
+
+	spin_lock(&server->req_lock);
+	scredits = *credits;
+	in_flight = server->in_flight;
+	spin_unlock(&server->req_lock);
+	return scredits >= num_credits || in_flight == 0;
+}
+
 static inline void
 add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits,
 	    const int optype)
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index f280502a2aee..82071142d72b 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -534,11 +534,21 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
 		spin_lock(&server->req_lock);
 		if (*credits < num_credits) {
 			scredits = *credits;
+			in_flight = server->in_flight;
+			if (in_flight == 0) {
+				spin_unlock(&server->req_lock);
+				trace_smb3_insufficient_credits(server->CurrentMid,
+						server->conn_id, server->hostname, scredits,
+						num_credits, in_flight);
+				cifs_dbg(FYI, "%s: %d requests in flight, needed %d total=%d\n",
+						__func__, in_flight, num_credits, scredits);
+				return -EDEADLK;
+			}
 			spin_unlock(&server->req_lock);
 
 			cifs_num_waiters_inc(server);
 			rc = wait_event_killable_timeout(server->request_q,
-				has_credits(server, credits, num_credits), t);
+				has_credits_or_insufficient(server, credits, num_credits), t);
 			cifs_num_waiters_dec(server);
 			if (!rc) {
 				spin_lock(&server->req_lock);
@@ -578,8 +588,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
 				cifs_num_waiters_inc(server);
 				rc = wait_event_killable_timeout(
 					server->request_q,
-					has_credits(server, credits,
-						    MAX_COMPOUND + 1),
+					has_credits_or_insufficient(server, credits,
+								MAX_COMPOUND + 1),
 					t);
 				cifs_num_waiters_dec(server);
 				if (!rc) {
-- 
2.40.1




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

  Powered by Linux