aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/CHANGES5
-rw-r--r--fs/cifs/cifssmb.c6
-rw-r--r--fs/cifs/connect.c40
-rw-r--r--fs/cifs/file.c3
-rw-r--r--fs/cifs/transport.c6
5 files changed, 53 insertions, 7 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index bd3b55e1be17..4d2404305ab6 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,10 @@
1Version 1.34 1Version 1.34
2------------ 2------------
3Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. 3Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
4Do not oops if user kills cifs oplock kernel thread. 4Do not oops if root user kills cifs oplock kernel thread or
5kills the cifsd thread (NB: killing the cifs kernel threads is not
6recommended, unmount and rmmod cifs will kill them when they are
7no longer needed).
5 8
6Version 1.33 9Version 1.33
7------------ 10------------
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f8edf816b4be..b004fef0a42b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -90,7 +90,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
90 check for tcp and smb session status done differently 90 check for tcp and smb session status done differently
91 for those three - in the calling routine */ 91 for those three - in the calling routine */
92 if(tcon) { 92 if(tcon) {
93 if((tcon->ses) && (tcon->ses->server)){ 93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94 (tcon->ses->server)){
94 struct nls_table *nls_codepage; 95 struct nls_table *nls_codepage;
95 /* Give Demultiplex thread up to 10 seconds to 96 /* Give Demultiplex thread up to 10 seconds to
96 reconnect, should be greater than cifs socket 97 reconnect, should be greater than cifs socket
@@ -185,7 +186,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
185 check for tcp and smb session status done differently 186 check for tcp and smb session status done differently
186 for those three - in the calling routine */ 187 for those three - in the calling routine */
187 if(tcon) { 188 if(tcon) {
188 if((tcon->ses) && (tcon->ses->server)){ 189 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
190 (tcon->ses->server)){
189 struct nls_table *nls_codepage; 191 struct nls_table *nls_codepage;
190 /* Give Demultiplex thread up to 10 seconds to 192 /* Give Demultiplex thread up to 10 seconds to
191 reconnect, should be greater than cifs socket 193 reconnect, should be greater than cifs socket
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,
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 1df26ddf68b1..dde2d251fc3d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -512,7 +512,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
512 pTcon = cifs_sb->tcon; 512 pTcon = cifs_sb->tcon;
513 513
514 cFYI(1, ("Freeing private data in close dir")); 514 cFYI(1, ("Freeing private data in close dir"));
515 if (pCFileStruct->srch_inf.endOfSearch == FALSE) { 515 if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
516 (pCFileStruct->invalidHandle == FALSE)) {
516 pCFileStruct->invalidHandle = TRUE; 517 pCFileStruct->invalidHandle = TRUE;
517 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); 518 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
518 cFYI(1, ("Closing uncompleted readdir with rc %d", 519 cFYI(1, ("Closing uncompleted readdir with rc %d",
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 79bf686a2a19..0046c219833d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -270,6 +270,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
270 270
271 271
272 272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT;
275
273 /* Ensure that we do not send more than 50 overlapping requests 276 /* Ensure that we do not send more than 50 overlapping requests
274 to the same server. We may make this configurable later or 277 to the same server. We may make this configurable later or
275 use ses->maxReq */ 278 use ses->maxReq */
@@ -401,6 +404,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
401 return -EIO; 404 return -EIO;
402 } 405 }
403 406
407 if(ses->server->tcpStatus == CifsExiting)
408 return -ENOENT;
409
404 /* Ensure that we do not send more than 50 overlapping requests 410 /* Ensure that we do not send more than 50 overlapping requests
405 to the same server. We may make this configurable later or 411 to the same server. We may make this configurable later or
406 use ses->maxReq */ 412 use ses->maxReq */