diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 40 |
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, |