Skip to content

Commit

Permalink
CIFS: Check for reconnects before sending compound requests
Browse files Browse the repository at this point in the history
The reconnect might have happended after we obtained credits
and before we acquired srv_mutex. Check for that under the mutex
and retry a sync operation if the reconnect is detected.

Signed-off-by: Pavel Shilovsky <[email protected]>
Signed-off-by: Steve French <[email protected]>
  • Loading branch information
piastry authored and Steve French committed Mar 6, 2019
1 parent 3349c3a commit 97ea499
Showing 1 changed file with 36 additions and 2 deletions.
38 changes: 36 additions & 2 deletions fs/cifs/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
{ .value = 0, .instance = 0 }
};
unsigned int instance;
unsigned int first_instance = 0;
char *buf;

timeout = flags & CIFS_TIMEOUT_MASK;
Expand Down Expand Up @@ -870,6 +871,25 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
for (i = 0; i < num_rqst; i++) {
rc = wait_for_free_request(ses->server, timeout, optype,
&instance);

if (rc == 0) {
credits[i].value = 1;
credits[i].instance = instance;
/*
* All parts of the compound chain must get credits from
* the same session, otherwise we may end up using more
* credits than the server granted. If there were
* reconnects in between, return -EAGAIN and let callers
* handle it.
*/
if (i == 0)
first_instance = instance;
else if (first_instance != instance) {
i++;
rc = -EAGAIN;
}
}

if (rc) {
/*
* We haven't sent an SMB packet to the server yet but
Expand All @@ -884,8 +904,6 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
add_credits(ses->server, &credits[j], optype);
return rc;
}
credits[i].value = 1;
credits[i].instance = instance;
}

/*
Expand All @@ -896,6 +914,22 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,

mutex_lock(&ses->server->srv_mutex);

/*
* All the parts of the compound chain belong obtained credits from the
* same session (see the appropriate checks above). In the same time
* there might be reconnects after those checks but before we acquired
* the srv_mutex. We can not use credits obtained from the previous
* session to send this request. Check if there were reconnects after
* we obtained credits and return -EAGAIN in such cases to let callers
* handle it.
*/
if (first_instance != ses->server->reconnect_instance) {
mutex_unlock(&ses->server->srv_mutex);
for (j = 0; j < num_rqst; j++)
add_credits(ses->server, &credits[j], optype);
return -EAGAIN;
}

for (i = 0; i < num_rqst; i++) {
midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]);
if (IS_ERR(midQ[i])) {
Expand Down

0 comments on commit 97ea499

Please sign in to comment.