[PATCH] cifs: Do not init smb requests or block when sending requests
authorSteve French <smfrench@austin.rr.com>
Fri, 29 Apr 2005 05:41:11 +0000 (22:41 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 29 Apr 2005 05:41:11 +0000 (22:41 -0700)
if cifsd thread is no longer running to demultixplex responses.

Do not send FindClose request when FindFirst failed without reaching end
of search.

Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/cifs/CHANGES
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/transport.c

index bd3b55e1be179c671cbdb94060bb580def15d113..4d2404305ab687c2a0eee84b3c5842ba9852965a 100644 (file)
@@ -1,7 +1,10 @@
 Version 1.34
 ------------
 Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
-Do not oops if user kills cifs oplock kernel thread.
+Do not oops if root user kills cifs oplock kernel thread or
+kills the cifsd thread (NB: killing the cifs kernel threads is not
+recommended, unmount and rmmod cifs will kill them when they are
+no longer needed).
 
 Version 1.33
 ------------
index f8edf816b4bed1de6a253cb45a553caea1af8276..b004fef0a42bac42e8b3490fba19df1ea233762d 100644 (file)
@@ -90,7 +90,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if(tcon) {
-               if((tcon->ses) && (tcon->ses->server)){
+               if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
+                                 (tcon->ses->server)){
                        struct nls_table *nls_codepage;
                                /* Give Demultiplex thread up to 10 seconds to 
                                   reconnect, should be greater than cifs socket
@@ -185,7 +186,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if(tcon) {
-               if((tcon->ses) && (tcon->ses->server)){
+               if((tcon->ses) && (tcon->ses->status != CifsExiting) && 
+                                 (tcon->ses->server)){
                        struct nls_table *nls_codepage;
                                /* Give Demultiplex thread up to 10 seconds to
                                   reconnect, should be greater than cifs socket
index 437be1efe99e2ac4a2047e43f660e94beaff39d3..ac1f970e5369749c8aaffbf52095d0bba7f374a5 100644 (file)
@@ -604,7 +604,13 @@ multi_t2_fnd:
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
        server->tsk = NULL;
-       atomic_set(&server->inFlight, 0);
+       /* check if we have blocked requests that need to free */
+       /* Note that cifs_max_pending is normally 50, but
+       can be set at module install time to as little as two */
+       if(atomic_read(&server->inFlight) >= cifs_max_pending)
+               atomic_set(&server->inFlight, cifs_max_pending - 1);
+       /* We do not want to set the max_pending too low or we
+       could end up with the counter going negative */
        spin_unlock(&GlobalMid_Lock);
        /* Although there should not be any requests blocked on 
        this queue it can not hurt to be paranoid and try to wake up requests
@@ -640,6 +646,17 @@ multi_t2_fnd:
                }
                read_unlock(&GlobalSMBSeslock);
        } else {
+               /* although we can not zero the server struct pointer yet,
+               since there are active requests which may depnd on them,
+               mark the corresponding SMB sessions as exiting too */
+               list_for_each(tmp, &GlobalSMBSessionList) {
+                       ses = list_entry(tmp, struct cifsSesInfo,
+                                        cifsSessionList);
+                       if (ses->server == server) {
+                               ses->status = CifsExiting;
+                       }
+               }
+
                spin_lock(&GlobalMid_Lock);
                list_for_each(tmp, &server->pending_mid_q) {
                mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
@@ -661,17 +678,34 @@ multi_t2_fnd:
        if (list_empty(&server->pending_mid_q)) {
                /* mpx threads have not exited yet give them 
                at least the smb send timeout time for long ops */
+               /* due to delays on oplock break requests, we need
+               to wait at least 45 seconds before giving up
+               on a request getting a response and going ahead
+               and killing cifsd */
                cFYI(1, ("Wait for exit from demultiplex thread"));
-               msleep(46);
+               msleep(46000);
                /* if threads still have not exited they are probably never
                coming home not much else we can do but free the memory */
        }
-       kfree(server);
 
        write_lock(&GlobalSMBSeslock);
        atomic_dec(&tcpSesAllocCount);
        length = tcpSesAllocCount.counter;
+
+       /* last chance to mark ses pointers invalid
+       if there are any pointing to this (e.g
+       if a crazy root user tried to kill cifsd 
+       kernel thread explicitly this might happen) */
+       list_for_each(tmp, &GlobalSMBSessionList) {
+               ses = list_entry(tmp, struct cifsSesInfo,
+                               cifsSessionList);
+               if (ses->server == server) {
+                       ses->server = NULL;
+               }
+       }
        write_unlock(&GlobalSMBSeslock);
+
+       kfree(server);
        if(length  > 0) {
                mempool_resize(cifs_req_poolp,
                        length + cifs_min_rcv,
index 1df26ddf68b1534f0602f5b8c2bca870814c4ca7..dde2d251fc3d6b0d387559bf5c590ede89bcf80a 100644 (file)
@@ -512,7 +512,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
                pTcon = cifs_sb->tcon;
 
                cFYI(1, ("Freeing private data in close dir"));
-               if (pCFileStruct->srch_inf.endOfSearch == FALSE) {
+               if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
+                  (pCFileStruct->invalidHandle == FALSE)) {
                        pCFileStruct->invalidHandle = TRUE;
                        rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
                        cFYI(1, ("Closing uncompleted readdir with rc %d",
index 79bf686a2a190875dcb37a239811659c2e2c95df..0046c219833d6cfbef77e85addc663e1be71e290 100644 (file)
@@ -270,6 +270,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
 
   
 
+       if(ses->server->tcpStatus == CIFS_EXITING)
+               return -ENOENT;
+
        /* Ensure that we do not send more than 50 overlapping requests 
           to the same server. We may make this configurable later or
           use ses->maxReq */
@@ -401,6 +404,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
                return -EIO;
        }
 
+       if(ses->server->tcpStatus == CifsExiting)
+               return -ENOENT;
+
        /* Ensure that we do not send more than 50 overlapping requests 
           to the same server. We may make this configurable later or
           use ses->maxReq */