CIFS: Check for reconnects before sending compound requests
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 <pshilov@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
3349c3a79f
commit
97ea499883
@ -843,6 +843,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
|||||||
{ .value = 0, .instance = 0 }
|
{ .value = 0, .instance = 0 }
|
||||||
};
|
};
|
||||||
unsigned int instance;
|
unsigned int instance;
|
||||||
|
unsigned int first_instance = 0;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
timeout = flags & CIFS_TIMEOUT_MASK;
|
timeout = flags & CIFS_TIMEOUT_MASK;
|
||||||
@ -870,6 +871,25 @@ 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_free_request(ses->server, timeout, optype,
|
rc = wait_for_free_request(ses->server, timeout, optype,
|
||||||
&instance);
|
&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) {
|
if (rc) {
|
||||||
/*
|
/*
|
||||||
* We haven't sent an SMB packet to the server yet but
|
* We haven't sent an SMB packet to the server yet but
|
||||||
@ -884,8 +904,6 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
|||||||
add_credits(ses->server, &credits[j], optype);
|
add_credits(ses->server, &credits[j], optype);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
credits[i].value = 1;
|
|
||||||
credits[i].instance = instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -896,6 +914,22 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
|||||||
|
|
||||||
mutex_lock(&ses->server->srv_mutex);
|
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++) {
|
for (i = 0; i < num_rqst; i++) {
|
||||||
midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]);
|
midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]);
|
||||||
if (IS_ERR(midQ[i])) {
|
if (IS_ERR(midQ[i])) {
|
||||||
|
Loading…
Reference in New Issue
Block a user