aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-05-22 07:09:13 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-23 23:11:33 -0400
commit3c1105df699188a70f5c17dc0795affea388bca7 (patch)
treebfbcfaaae2fdfd16b2fcdb57710b9affbf183c49 /fs/cifs/transport.c
parent724d9f1cfba0cb16a7151333b501e8f7885450d8 (diff)
cifs: don't call mid_q_entry->callback under the Global_MidLock (try #5)
Minor revision to the last version of this patch -- the only difference is the fix to the cFYI statement in cifs_reconnect. Holding the spinlock while we call this function means that it can't sleep, which really limits what it can do. Taking it out from under the spinlock also means less contention for this global lock. Change the semantics such that the Global_MidLock is not held when the callback is called. To do this requires that we take extra care not to have sync_mid_result remove the mid from the list when the mid is in a state where that has already happened. This prevents list corruption when the mid is sitting on a private list for reconnect or when cifsd is coming down. Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru> 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.c23
1 files changed, 8 insertions, 15 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 16bcc0725cee..d1998b6086ef 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -426,7 +426,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
426} 426}
427 427
428static int 428static int
429sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) 429cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
430{ 430{
431 int rc = 0; 431 int rc = 0;
432 432
@@ -434,28 +434,21 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
434 mid->mid, mid->midState); 434 mid->mid, mid->midState);
435 435
436 spin_lock(&GlobalMid_Lock); 436 spin_lock(&GlobalMid_Lock);
437 /* ensure that it's no longer on the pending_mid_q */
438 list_del_init(&mid->qhead);
439
440 switch (mid->midState) { 437 switch (mid->midState) {
441 case MID_RESPONSE_RECEIVED: 438 case MID_RESPONSE_RECEIVED:
442 spin_unlock(&GlobalMid_Lock); 439 spin_unlock(&GlobalMid_Lock);
443 return rc; 440 return rc;
444 case MID_REQUEST_SUBMITTED:
445 /* socket is going down, reject all calls */
446 if (server->tcpStatus == CifsExiting) {
447 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
448 __func__, mid->mid, mid->command, mid->midState);
449 rc = -EHOSTDOWN;
450 break;
451 }
452 case MID_RETRY_NEEDED: 441 case MID_RETRY_NEEDED:
453 rc = -EAGAIN; 442 rc = -EAGAIN;
454 break; 443 break;
455 case MID_RESPONSE_MALFORMED: 444 case MID_RESPONSE_MALFORMED:
456 rc = -EIO; 445 rc = -EIO;
457 break; 446 break;
447 case MID_SHUTDOWN:
448 rc = -EHOSTDOWN;
449 break;
458 default: 450 default:
451 list_del_init(&mid->qhead);
459 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, 452 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
460 mid->mid, mid->midState); 453 mid->mid, mid->midState);
461 rc = -EIO; 454 rc = -EIO;
@@ -618,7 +611,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
618 611
619 cifs_small_buf_release(in_buf); 612 cifs_small_buf_release(in_buf);
620 613
621 rc = sync_mid_result(midQ, ses->server); 614 rc = cifs_sync_mid_result(midQ, ses->server);
622 if (rc != 0) { 615 if (rc != 0) {
623 atomic_dec(&ses->server->inFlight); 616 atomic_dec(&ses->server->inFlight);
624 wake_up(&ses->server->request_q); 617 wake_up(&ses->server->request_q);
@@ -739,7 +732,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
739 spin_unlock(&GlobalMid_Lock); 732 spin_unlock(&GlobalMid_Lock);
740 } 733 }
741 734
742 rc = sync_mid_result(midQ, ses->server); 735 rc = cifs_sync_mid_result(midQ, ses->server);
743 if (rc != 0) { 736 if (rc != 0) {
744 atomic_dec(&ses->server->inFlight); 737 atomic_dec(&ses->server->inFlight);
745 wake_up(&ses->server->request_q); 738 wake_up(&ses->server->request_q);
@@ -914,7 +907,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
914 rstart = 1; 907 rstart = 1;
915 } 908 }
916 909
917 rc = sync_mid_result(midQ, ses->server); 910 rc = cifs_sync_mid_result(midQ, ses->server);
918 if (rc != 0) 911 if (rc != 0)
919 return rc; 912 return rc;
920 913