aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-05-11 11:53:33 -0400
committerSteve French <sfrench@us.ibm.com>2008-05-11 13:45:44 -0400
commite691b9d1a096fbaaff9d6d6aef1adc593b786e62 (patch)
treea329a4d115315d4dd459d171c3c98b2bc8c4728b
parent67750fb9e07940c078d1edb16fd736ccc92a4a4e (diff)
[CIFS] don't allow demultiplex thread to exit until kthread_stop is called
cifs_demultiplex_thread can exit under several conditions: 1) if it's signaled 2) if there's a problem with session setup 3) if kthread_stop is called on it The first two are problems. If kthread_stop is called on the thread, there is no guarantee that it will still be up. We need to have the thread stay up until kthread_stop is called on it. One option would be to not even try to tear things down until after kthread_stop is called. However, in the case where there is a problem setting up the session, there's no real reason to try continuing the loop. This patch allows the thread to clean up and prepare for exit under all three conditions, but it has the thread go to sleep until kthread_stop is called. This allows us to simplify the shutdown code somewhat since we can be reasonably sure that the thread won't exit after being signaled but before kthread_stop is called. It also removes the places where the thread itself set the tsk variable since it appeared that it could have a potential race where the thread might never be shut down. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/connect.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 965050867599..f428bf3bf1a9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -348,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
348 int reconnect; 348 int reconnect;
349 349
350 current->flags |= PF_MEMALLOC; 350 current->flags |= PF_MEMALLOC;
351 server->tsk = current; /* save process info to wake at shutdown */
352 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); 351 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
353 write_lock(&GlobalSMBSeslock); 352 write_lock(&GlobalSMBSeslock);
354 atomic_inc(&tcpSesAllocCount); 353 atomic_inc(&tcpSesAllocCount);
@@ -651,10 +650,20 @@ multi_t2_fnd:
651 650
652 spin_lock(&GlobalMid_Lock); 651 spin_lock(&GlobalMid_Lock);
653 server->tcpStatus = CifsExiting; 652 server->tcpStatus = CifsExiting;
654 server->tsk = NULL; 653 spin_unlock(&GlobalMid_Lock);
654
655 /* don't exit until kthread_stop is called */
656 set_current_state(TASK_UNINTERRUPTIBLE);
657 while (!kthread_should_stop()) {
658 schedule();
659 set_current_state(TASK_UNINTERRUPTIBLE);
660 }
661 set_current_state(TASK_RUNNING);
662
655 /* check if we have blocked requests that need to free */ 663 /* check if we have blocked requests that need to free */
656 /* Note that cifs_max_pending is normally 50, but 664 /* Note that cifs_max_pending is normally 50, but
657 can be set at module install time to as little as two */ 665 can be set at module install time to as little as two */
666 spin_lock(&GlobalMid_Lock);
658 if (atomic_read(&server->inFlight) >= cifs_max_pending) 667 if (atomic_read(&server->inFlight) >= cifs_max_pending)
659 atomic_set(&server->inFlight, cifs_max_pending - 1); 668 atomic_set(&server->inFlight, cifs_max_pending - 1);
660 /* We do not want to set the max_pending too low or we 669 /* We do not want to set the max_pending too low or we
@@ -2187,15 +2196,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2187 srvTcp->tcpStatus = CifsExiting; 2196 srvTcp->tcpStatus = CifsExiting;
2188 spin_unlock(&GlobalMid_Lock); 2197 spin_unlock(&GlobalMid_Lock);
2189 if (srvTcp->tsk) { 2198 if (srvTcp->tsk) {
2190 struct task_struct *tsk;
2191 /* If we could verify that kthread_stop would 2199 /* If we could verify that kthread_stop would
2192 always wake up processes blocked in 2200 always wake up processes blocked in
2193 tcp in recv_mesg then we could remove the 2201 tcp in recv_mesg then we could remove the
2194 send_sig call */ 2202 send_sig call */
2195 force_sig(SIGKILL, srvTcp->tsk); 2203 force_sig(SIGKILL, srvTcp->tsk);
2196 tsk = srvTcp->tsk; 2204 kthread_stop(srvTcp->tsk);
2197 if (tsk)
2198 kthread_stop(tsk);
2199 } 2205 }
2200 } 2206 }
2201 /* If find_unc succeeded then rc == 0 so we can not end */ 2207 /* If find_unc succeeded then rc == 0 so we can not end */
@@ -2211,23 +2217,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2211 if ((temp_rc == -ESHUTDOWN) && 2217 if ((temp_rc == -ESHUTDOWN) &&
2212 (pSesInfo->server) && 2218 (pSesInfo->server) &&
2213 (pSesInfo->server->tsk)) { 2219 (pSesInfo->server->tsk)) {
2214 struct task_struct *tsk;
2215 force_sig(SIGKILL, 2220 force_sig(SIGKILL,
2216 pSesInfo->server->tsk); 2221 pSesInfo->server->tsk);
2217 tsk = pSesInfo->server->tsk; 2222 kthread_stop(pSesInfo->server->tsk);
2218 if (tsk)
2219 kthread_stop(tsk);
2220 } 2223 }
2221 } else { 2224 } else {
2222 cFYI(1, ("No session or bad tcon")); 2225 cFYI(1, ("No session or bad tcon"));
2223 if ((pSesInfo->server) && 2226 if ((pSesInfo->server) &&
2224 (pSesInfo->server->tsk)) { 2227 (pSesInfo->server->tsk)) {
2225 struct task_struct *tsk;
2226 force_sig(SIGKILL, 2228 force_sig(SIGKILL,
2227 pSesInfo->server->tsk); 2229 pSesInfo->server->tsk);
2228 tsk = pSesInfo->server->tsk; 2230 kthread_stop(pSesInfo->server->tsk);
2229 if (tsk)
2230 kthread_stop(tsk);
2231 } 2231 }
2232 } 2232 }
2233 sesInfoFree(pSesInfo); 2233 sesInfoFree(pSesInfo);