@@ -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)
@@ -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) {
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@uniontech.com> --- fs/smb/client/cifsglob.h | 13 +++++++++++++ fs/smb/client/transport.c | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-)