[linux-cifs-client] [PATCH 4/4] [CIFS] don't allow demultiplex
thread to exit until kthread_stop is called
Shirish Pargaonkar
shirishpargaonkar at gmail.com
Sun May 4 15:46:00 GMT 2008
On 5/2/08, Jeff Layton <jlayton at redhat.com> wrote:
> 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 at redhat.com>
> ---
> fs/cifs/connect.c | 28 ++++++++++++++--------------
> 1 files changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 4c93c2a..f904713 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -348,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
> int reconnect;
>
> current->flags |= PF_MEMALLOC;
> - server->tsk = current; /* save process info to wake at shutdown */
> cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
>
> length = atomic_inc_return(&tcpSesAllocCount);
> @@ -649,10 +648,20 @@ multi_t2_fnd:
>
> spin_lock(&GlobalMid_Lock);
> server->tcpStatus = CifsExiting;
> - server->tsk = NULL;
> + spin_unlock(&GlobalMid_Lock);
> +
> + /* don't exit until kthread_stop is called */
> + set_current_state(TASK_UNINTERRUPTIBLE);
> + while (!kthread_should_stop()) {
> + schedule();
> + set_current_state(TASK_UNINTERRUPTIBLE);
> + }
> + set_current_state(TASK_RUNNING);
> +
> /* 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 */
> + spin_lock(&GlobalMid_Lock);
> 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
> @@ -2182,15 +2191,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
> srvTcp->tcpStatus = CifsExiting;
> spin_unlock(&GlobalMid_Lock);
> if (srvTcp->tsk) {
> - struct task_struct *tsk;
> /* If we could verify that kthread_stop would
> always wake up processes blocked in
> tcp in recv_mesg then we could remove the
> send_sig call */
> force_sig(SIGKILL, srvTcp->tsk);
> - tsk = srvTcp->tsk;
> - if (tsk)
> - kthread_stop(tsk);
> + kthread_stop(srvTcp->tsk);
> }
> }
> /* If find_unc succeeded then rc == 0 so we can not end */
> @@ -2206,23 +2212,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
> if ((temp_rc == -ESHUTDOWN) &&
> (pSesInfo->server) &&
> (pSesInfo->server->tsk)) {
> - struct task_struct *tsk;
> force_sig(SIGKILL,
> pSesInfo->server->tsk);
> - tsk = pSesInfo->server->tsk;
> - if (tsk)
> - kthread_stop(tsk);
> + kthread_stop(pSesInfo->server->tsk);
> }
> } else {
> cFYI(1, ("No session or bad tcon"));
> if ((pSesInfo->server) &&
> (pSesInfo->server->tsk)) {
> - struct task_struct *tsk;
> force_sig(SIGKILL,
> pSesInfo->server->tsk);
> - tsk = pSesInfo->server->tsk;
> - if (tsk)
> - kthread_stop(tsk);
> + kthread_stop(pSesInfo->server->tsk);
> }
> }
> sesInfoFree(pSesInfo);
> --
> 1.5.3.6
>
> _______________________________________________
> linux-cifs-client mailing list
> linux-cifs-client at lists.samba.org
> https://lists.samba.org/mailman/listinfo/linux-cifs-client
>
Jeff,
Is there a possibility that kthread_stop would never get called, in which
case cifsd would loop forever or for a long long time i.e. cifsd has become
useless but would not go away, sort of wasting system resources however
miniscule?
I think this can only happen if kernel_recvmsg returns with return code EINTR
not because it was sig(kill)naled by mount or unmount code but for some
other reason!
Regards,
Shirish
More information about the linux-cifs-client
mailing list