Commit 7091bcab authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Try to acquire credits at once for compound requests

Currently we get one credit per compound part of the request
individually. This may lead to being stuck on waiting for credits
if multiple compounded operations happen in parallel. Try acquire
credits for all compound parts at once. Return immediately if not
enough credits and too few requests are in flight currently thus
narrowing the possibility of infinite waiting for credits.

The more advance fix is to return right away if not enough credits
for the compound request and do not look at the number of requests
in flight. The caller should handle such situations by falling back
to sequential execution of SMB commands instead of compounding.
Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent fe768d51
...@@ -860,13 +860,41 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -860,13 +860,41 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
if (ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
return -ENOENT; return -ENOENT;
spin_lock(&ses->server->req_lock);
if (ses->server->credits < num_rqst) {
/* /*
* Return immediately if not too many requests in flight since
* we will likely be stuck on waiting for credits.
*/
if (ses->server->in_flight < num_rqst - ses->server->credits) {
spin_unlock(&ses->server->req_lock);
return -ENOTSUPP;
}
} else {
/* enough credits to send the whole compounded request */
ses->server->credits -= num_rqst;
ses->server->in_flight += num_rqst;
first_instance = ses->server->reconnect_instance;
}
spin_unlock(&ses->server->req_lock);
if (first_instance) {
cifs_dbg(FYI, "Acquired %d credits at once\n", num_rqst);
for (i = 0; i < num_rqst; i++) {
credits[i].value = 1;
credits[i].instance = first_instance;
}
goto setup_rqsts;
}
/*
* There are not enough credits to send the whole compound request but
* there are requests in flight that may bring credits from the server.
* This approach still leaves the possibility to be stuck waiting for
* credits if the server doesn't grant credits to the outstanding
* requests. This should be fixed by returning immediately and letting
* a caller fallback to sequential commands instead of compounding.
* Ensure we obtain 1 credit per request in the compound chain. * Ensure we obtain 1 credit per request in the compound chain.
* It can be optimized further by waiting for all the credits
* at once but this can wait long enough if we don't have enough
* credits due to some heavy operations in progress or the server
* not granting us much, so a fallback to the current approach is
* needed anyway.
*/ */
for (i = 0; i < num_rqst; i++) { for (i = 0; i < num_rqst; i++) {
rc = wait_for_free_request(ses->server, timeout, optype, rc = wait_for_free_request(ses->server, timeout, optype,
...@@ -906,6 +934,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -906,6 +934,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
} }
} }
setup_rqsts:
/* /*
* Make sure that we sign in the same order that we send on this socket * Make sure that we sign in the same order that we send on this socket
* and avoid races inside tcp sendmsg code that could cause corruption * and avoid races inside tcp sendmsg code that could cause corruption
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment