aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 437be1efe99e..ac1f970e5369 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -604,7 +604,13 @@ multi_t2_fnd:
604 spin_lock(&GlobalMid_Lock); 604 spin_lock(&GlobalMid_Lock);
605 server->tcpStatus = CifsExiting; 605 server->tcpStatus = CifsExiting;
606 server->tsk = NULL; 606 server->tsk = NULL;
607 atomic_set(&server->inFlight, 0); 607 /* check if we have blocked requests that need to free */
608 /* Note that cifs_max_pending is normally 50, but
609 can be set at module install time to as little as two */
610 if(atomic_read(&server->inFlight) >= cifs_max_pending)
611 atomic_set(&server->inFlight, cifs_max_pending - 1);
612 /* We do not want to set the max_pending too low or we
613 could end up with the counter going negative */
608 spin_unlock(&GlobalMid_Lock); 614 spin_unlock(&GlobalMid_Lock);
609 /* Although there should not be any requests blocked on 615 /* Although there should not be any requests blocked on
610 this queue it can not hurt to be paranoid and try to wake up requests 616 this queue it can not hurt to be paranoid and try to wake up requests
@@ -640,6 +646,17 @@ multi_t2_fnd:
640 } 646 }
641 read_unlock(&GlobalSMBSeslock); 647 read_unlock(&GlobalSMBSeslock);
642 } else { 648 } else {
649 /* although we can not zero the server struct pointer yet,
650 since there are active requests which may depnd on them,
651 mark the corresponding SMB sessions as exiting too */
652 list_for_each(tmp, &GlobalSMBSessionList) {
653 ses = list_entry(tmp, struct cifsSesInfo,
654 cifsSessionList);
655 if (ses->server == server) {
656 ses->status = CifsExiting;
657 }
658 }
659
643 spin_lock(&GlobalMid_Lock); 660 spin_lock(&GlobalMid_Lock);
644 list_for_each(tmp, &server->pending_mid_q) { 661 list_for_each(tmp, &server->pending_mid_q) {
645 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 662 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
@@ -661,17 +678,34 @@ multi_t2_fnd:
661 if (list_empty(&server->pending_mid_q)) { 678 if (list_empty(&server->pending_mid_q)) {
662 /* mpx threads have not exited yet give them 679 /* mpx threads have not exited yet give them
663 at least the smb send timeout time for long ops */ 680 at least the smb send timeout time for long ops */
681 /* due to delays on oplock break requests, we need
682 to wait at least 45 seconds before giving up
683 on a request getting a response and going ahead
684 and killing cifsd */
664 cFYI(1, ("Wait for exit from demultiplex thread")); 685 cFYI(1, ("Wait for exit from demultiplex thread"));
665 msleep(46); 686 msleep(46000);
666 /* if threads still have not exited they are probably never 687 /* if threads still have not exited they are probably never
667 coming home not much else we can do but free the memory */ 688 coming home not much else we can do but free the memory */
668 } 689 }
669 kfree(server);
670 690
671 write_lock(&GlobalSMBSeslock); 691 write_lock(&GlobalSMBSeslock);
672 atomic_dec(&tcpSesAllocCount); 692 atomic_dec(&tcpSesAllocCount);
673 length = tcpSesAllocCount.counter; 693 length = tcpSesAllocCount.counter;
694
695 /* last chance to mark ses pointers invalid
696 if there are any pointing to this (e.g
697 if a crazy root user tried to kill cifsd
698 kernel thread explicitly this might happen) */
699 list_for_each(tmp, &GlobalSMBSessionList) {
700 ses = list_entry(tmp, struct cifsSesInfo,
701 cifsSessionList);
702 if (ses->server == server) {
703 ses->server = NULL;
704 }
705 }
674 write_unlock(&GlobalSMBSeslock); 706 write_unlock(&GlobalSMBSeslock);
707
708 kfree(server);
675 if(length > 0) { 709 if(length > 0) {
676 mempool_resize(cifs_req_poolp, 710 mempool_resize(cifs_req_poolp,
677 length + cifs_min_rcv, 711 length + cifs_min_rcv,