Commit 1be912dd authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: handle cancelled requests better

Currently, when a request is cancelled via signal, we delete the mid
immediately. If the request was already transmitted however, the client
is still likely to receive a response. When it does, it won't recognize
it however and will pop a printk.

It's also a little dangerous to just delete the mid entry like this. We
may end up reusing that mid. If we do then we could potentially get the
response from the first request confused with the later one.

Prevent the reuse of mids by marking them as cancelled and keeping them
on the pending_mid_q list. If the reply comes in, we'll delete it from
the list then. If it never comes, then we'll delete it at reconnect
or when cifsd comes down.
Reviewed-by: default avatarPavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 58b8a5b4
...@@ -579,8 +579,17 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -579,8 +579,17 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
goto out; goto out;
rc = wait_for_response(ses->server, midQ); rc = wait_for_response(ses->server, midQ);
if (rc != 0) if (rc != 0) {
goto out; spin_lock(&GlobalMid_Lock);
if (midQ->midState == MID_REQUEST_SUBMITTED) {
midQ->callback = DeleteMidQEntry;
spin_unlock(&GlobalMid_Lock);
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
return rc;
}
spin_unlock(&GlobalMid_Lock);
}
rc = sync_mid_result(midQ, ses->server); rc = sync_mid_result(midQ, ses->server);
if (rc != 0) { if (rc != 0) {
...@@ -724,8 +733,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -724,8 +733,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
goto out; goto out;
rc = wait_for_response(ses->server, midQ); rc = wait_for_response(ses->server, midQ);
if (rc != 0) if (rc != 0) {
goto out; spin_lock(&GlobalMid_Lock);
if (midQ->midState == MID_REQUEST_SUBMITTED) {
/* no longer considered to be "in-flight" */
midQ->callback = DeleteMidQEntry;
spin_unlock(&GlobalMid_Lock);
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
return rc;
}
spin_unlock(&GlobalMid_Lock);
}
rc = sync_mid_result(midQ, ses->server); rc = sync_mid_result(midQ, ses->server);
if (rc != 0) { if (rc != 0) {
...@@ -922,11 +941,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -922,11 +941,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
} }
} }
if (wait_for_response(ses->server, midQ) == 0) { rc = wait_for_response(ses->server, midQ);
if (rc) {
spin_lock(&GlobalMid_Lock);
if (midQ->midState == MID_REQUEST_SUBMITTED) {
/* no longer considered to be "in-flight" */
midQ->callback = DeleteMidQEntry;
spin_unlock(&GlobalMid_Lock);
return rc;
}
spin_unlock(&GlobalMid_Lock);
}
/* We got the response - restart system call. */ /* We got the response - restart system call. */
rstart = 1; rstart = 1;
} }
}
rc = sync_mid_result(midQ, ses->server); rc = sync_mid_result(midQ, ses->server);
if (rc != 0) if (rc != 0)
......
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