aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-01-28 07:08:28 -0500
committerSteve French <sfrench@us.ibm.com>2011-01-30 23:23:31 -0500
commit1be912dde772b77aaaa21770eeabb0a7a5e297a6 (patch)
tree2f3a01093c80ea90675b2d8102ecc7f5dcf9ccae /fs/cifs/transport.c
parent58b8a5b45a097b477c037bc376e65dc5f214bf3d (diff)
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: Pavel Shilovsky <piastryyy@gmail.com> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index c1ccca1a933f..9b2d0373a8a7 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -579,8 +579,17 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
579 goto out; 579 goto out;
580 580
581 rc = wait_for_response(ses->server, midQ); 581 rc = wait_for_response(ses->server, midQ);
582 if (rc != 0) 582 if (rc != 0) {
583 goto out; 583 spin_lock(&GlobalMid_Lock);
584 if (midQ->midState == MID_REQUEST_SUBMITTED) {
585 midQ->callback = DeleteMidQEntry;
586 spin_unlock(&GlobalMid_Lock);
587 atomic_dec(&ses->server->inFlight);
588 wake_up(&ses->server->request_q);
589 return rc;
590 }
591 spin_unlock(&GlobalMid_Lock);
592 }
584 593
585 rc = sync_mid_result(midQ, ses->server); 594 rc = sync_mid_result(midQ, ses->server);
586 if (rc != 0) { 595 if (rc != 0) {
@@ -724,8 +733,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
724 goto out; 733 goto out;
725 734
726 rc = wait_for_response(ses->server, midQ); 735 rc = wait_for_response(ses->server, midQ);
727 if (rc != 0) 736 if (rc != 0) {
728 goto out; 737 spin_lock(&GlobalMid_Lock);
738 if (midQ->midState == MID_REQUEST_SUBMITTED) {
739 /* no longer considered to be "in-flight" */
740 midQ->callback = DeleteMidQEntry;
741 spin_unlock(&GlobalMid_Lock);
742 atomic_dec(&ses->server->inFlight);
743 wake_up(&ses->server->request_q);
744 return rc;
745 }
746 spin_unlock(&GlobalMid_Lock);
747 }
729 748
730 rc = sync_mid_result(midQ, ses->server); 749 rc = sync_mid_result(midQ, ses->server);
731 if (rc != 0) { 750 if (rc != 0) {
@@ -922,10 +941,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
922 } 941 }
923 } 942 }
924 943
925 if (wait_for_response(ses->server, midQ) == 0) { 944 rc = wait_for_response(ses->server, midQ);
926 /* We got the response - restart system call. */ 945 if (rc) {
927 rstart = 1; 946 spin_lock(&GlobalMid_Lock);
947 if (midQ->midState == MID_REQUEST_SUBMITTED) {
948 /* no longer considered to be "in-flight" */
949 midQ->callback = DeleteMidQEntry;
950 spin_unlock(&GlobalMid_Lock);
951 return rc;
952 }
953 spin_unlock(&GlobalMid_Lock);
928 } 954 }
955
956 /* We got the response - restart system call. */
957 rstart = 1;
929 } 958 }
930 959
931 rc = sync_mid_result(midQ, ses->server); 960 rc = sync_mid_result(midQ, ses->server);