Commit 3349c3a7 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Check for reconnects before sending async requests

The reconnect might have happended after we obtained credits
and before we acquired srv_mutex. Check for that under the mutex
and retry an async operation if the reconnect is detected.
Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 34f4deb7
...@@ -93,7 +93,8 @@ extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); ...@@ -93,7 +93,8 @@ extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
extern int cifs_call_async(struct TCP_Server_Info *server, extern int cifs_call_async(struct TCP_Server_Info *server,
struct smb_rqst *rqst, struct smb_rqst *rqst,
mid_receive_t *receive, mid_callback_t *callback, mid_receive_t *receive, mid_callback_t *callback,
mid_handle_t *handle, void *cbdata, const int flags); mid_handle_t *handle, void *cbdata, const int flags,
const struct cifs_credits *exist_credits);
extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
struct smb_rqst *rqst, int *resp_buf_type, struct smb_rqst *rqst, int *resp_buf_type,
const int flags, struct kvec *resp_iov); const int flags, struct kvec *resp_iov);
......
...@@ -860,7 +860,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server) ...@@ -860,7 +860,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
iov[1].iov_base = (char *)smb + 4; iov[1].iov_base = (char *)smb + 4;
rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL, rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
server, CIFS_ASYNC_OP | CIFS_ECHO_OP); server, CIFS_ASYNC_OP | CIFS_ECHO_OP, NULL);
if (rc) if (rc)
cifs_dbg(FYI, "Echo request failed: %d\n", rc); cifs_dbg(FYI, "Echo request failed: %d\n", rc);
...@@ -1812,7 +1812,7 @@ cifs_async_readv(struct cifs_readdata *rdata) ...@@ -1812,7 +1812,7 @@ cifs_async_readv(struct cifs_readdata *rdata)
kref_get(&rdata->refcount); kref_get(&rdata->refcount);
rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
cifs_readv_callback, NULL, rdata, 0); cifs_readv_callback, NULL, rdata, 0, NULL);
if (rc == 0) if (rc == 0)
cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
...@@ -2352,7 +2352,7 @@ cifs_async_writev(struct cifs_writedata *wdata, ...@@ -2352,7 +2352,7 @@ cifs_async_writev(struct cifs_writedata *wdata,
kref_get(&wdata->refcount); kref_get(&wdata->refcount);
rc = cifs_call_async(tcon->ses->server, &rqst, NULL, rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
cifs_writev_callback, NULL, wdata, 0); cifs_writev_callback, NULL, wdata, 0, NULL);
if (rc == 0) if (rc == 0)
cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
......
...@@ -3034,7 +3034,7 @@ SMB2_echo(struct TCP_Server_Info *server) ...@@ -3034,7 +3034,7 @@ SMB2_echo(struct TCP_Server_Info *server)
iov[0].iov_base = (char *)req; iov[0].iov_base = (char *)req;
rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL, rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
server, CIFS_ECHO_OP); server, CIFS_ECHO_OP, NULL);
if (rc) if (rc)
cifs_dbg(FYI, "Echo request failed: %d\n", rc); cifs_dbg(FYI, "Echo request failed: %d\n", rc);
...@@ -3343,7 +3343,8 @@ smb2_async_readv(struct cifs_readdata *rdata) ...@@ -3343,7 +3343,8 @@ smb2_async_readv(struct cifs_readdata *rdata)
kref_get(&rdata->refcount); kref_get(&rdata->refcount);
rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, rc = cifs_call_async(io_parms.tcon->ses->server, &rqst,
cifs_readv_receive, smb2_readv_callback, cifs_readv_receive, smb2_readv_callback,
smb3_handle_read_data, rdata, flags); smb3_handle_read_data, rdata, flags,
&rdata->credits);
if (rc) { if (rc) {
kref_put(&rdata->refcount, cifs_readdata_release); kref_put(&rdata->refcount, cifs_readdata_release);
cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
...@@ -3645,7 +3646,7 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -3645,7 +3646,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
kref_get(&wdata->refcount); kref_get(&wdata->refcount);
rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
wdata, flags); wdata, flags, &wdata->credits);
if (rc) { if (rc) {
trace_smb3_write_err(0 /* no xid */, req->PersistentFileId, trace_smb3_write_err(0 /* no xid */, req->PersistentFileId,
......
...@@ -607,7 +607,8 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) ...@@ -607,7 +607,8 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
int int
cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
mid_receive_t *receive, mid_callback_t *callback, mid_receive_t *receive, mid_callback_t *callback,
mid_handle_t *handle, void *cbdata, const int flags) mid_handle_t *handle, void *cbdata, const int flags,
const struct cifs_credits *exist_credits)
{ {
int rc, timeout, optype; int rc, timeout, optype;
struct mid_q_entry *mid; struct mid_q_entry *mid;
...@@ -623,9 +624,22 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, ...@@ -623,9 +624,22 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
return rc; return rc;
credits.value = 1; credits.value = 1;
credits.instance = instance; credits.instance = instance;
} } else
instance = exist_credits->instance;
mutex_lock(&server->srv_mutex); mutex_lock(&server->srv_mutex);
/*
* We can't 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 (instance != server->reconnect_instance) {
mutex_unlock(&server->srv_mutex);
add_credits_and_wake_if(server, &credits, optype);
return -EAGAIN;
}
mid = server->ops->setup_async_request(server, rqst); mid = server->ops->setup_async_request(server, rqst);
if (IS_ERR(mid)) { if (IS_ERR(mid)) {
mutex_unlock(&server->srv_mutex); mutex_unlock(&server->srv_mutex);
......
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