Skip to content

Commit

Permalink
cifs: handle cancelled requests better
Browse files Browse the repository at this point in the history
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: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
  • Loading branch information
Jeff Layton authored and Steve French committed Jan 31, 2011
1 parent 58b8a5b commit 1be912d
Showing 1 changed file with 36 additions and 7 deletions.
43 changes: 36 additions & 7 deletions fs/cifs/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,8 +579,17 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
goto out;

rc = wait_for_response(ses->server, midQ);
if (rc != 0)
goto out;
if (rc != 0) {
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);
if (rc != 0) {
Expand Down Expand Up @@ -724,8 +733,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
goto out;

rc = wait_for_response(ses->server, midQ);
if (rc != 0)
goto out;
if (rc != 0) {
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);
if (rc != 0) {
Expand Down Expand Up @@ -922,10 +941,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
}
}

if (wait_for_response(ses->server, midQ) == 0) {
/* We got the response - restart system call. */
rstart = 1;
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. */
rstart = 1;
}

rc = sync_mid_result(midQ, ses->server);
Expand Down

0 comments on commit 1be912d

Please sign in to comment.