Commit 8a26f0f7 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Fix credits calculation for cancelled requests

If a request is cancelled, we can't assume that the server returns
1 credit back. Instead we need to wait for a response and process
the number of credits granted by the server.

Create a separate mid callback for cancelled request, parse the number
of credits in a response buffer and add them to the client's credits.
If the didn't get a response (no response buffer available) assume
0 credits granted. The latter most probably happens together with
session reconnect, so the client's credits are adjusted anyway.
Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent b9a74cde
...@@ -1438,6 +1438,7 @@ struct mid_q_entry { ...@@ -1438,6 +1438,7 @@ struct mid_q_entry {
int mid_state; /* wish this were enum but can not pass to wait_event */ int mid_state; /* wish this were enum but can not pass to wait_event */
unsigned int mid_flags; unsigned int mid_flags;
__le16 command; /* smb command code */ __le16 command; /* smb command code */
unsigned int optype; /* operation type */
bool large_buf:1; /* if valid response, is pointer to large buf */ bool large_buf:1; /* if valid response, is pointer to large buf */
bool multiRsp:1; /* multiple trans2 responses for one request */ bool multiRsp:1; /* multiple trans2 responses for one request */
bool multiEnd:1; /* both received */ bool multiEnd:1; /* both received */
......
...@@ -787,6 +787,24 @@ cifs_noop_callback(struct mid_q_entry *mid) ...@@ -787,6 +787,24 @@ cifs_noop_callback(struct mid_q_entry *mid)
{ {
} }
static void
cifs_cancelled_callback(struct mid_q_entry *mid)
{
struct TCP_Server_Info *server = mid->server;
unsigned int optype = mid->optype;
unsigned int credits_received = 0;
if (mid->mid_state == MID_RESPONSE_RECEIVED) {
if (mid->resp_buf)
credits_received = server->ops->get_credits(mid);
else
cifs_dbg(FYI, "Bad state for cancelled MID\n");
}
DeleteMidQEntry(mid);
add_credits(server, credits_received, optype);
}
int int
compound_send_recv(const unsigned int xid, struct cifs_ses *ses, compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
const int flags, const int num_rqst, struct smb_rqst *rqst, const int flags, const int num_rqst, struct smb_rqst *rqst,
...@@ -862,6 +880,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -862,6 +880,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
} }
midQ[i]->mid_state = MID_REQUEST_SUBMITTED; midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
midQ[i]->optype = optype;
/* /*
* We don't invoke the callback compounds unless it is the last * We don't invoke the callback compounds unless it is the last
* request. * request.
...@@ -896,15 +915,20 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -896,15 +915,20 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
for (i = 0; i < num_rqst; i++) { for (i = 0; i < num_rqst; i++) {
rc = wait_for_response(ses->server, midQ[i]); rc = wait_for_response(ses->server, midQ[i]);
if (rc != 0) { if (rc != 0)
break;
}
if (rc != 0) {
for (; i < num_rqst; i++) {
cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n",
midQ[i]->mid, le16_to_cpu(midQ[i]->command)); midQ[i]->mid, le16_to_cpu(midQ[i]->command));
send_cancel(ses->server, &rqst[i], midQ[i]); send_cancel(ses->server, &rqst[i], midQ[i]);
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
midQ[i]->mid_flags |= MID_WAIT_CANCELLED; midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
midQ[i]->callback = DeleteMidQEntry; midQ[i]->callback = cifs_cancelled_callback;
cancelled_mid[i] = true; cancelled_mid[i] = true;
credits[i] = 0;
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
} }
......
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