]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nfsd: don't allow nfsd threads to be signalled.
authorChuck Lever <chuck.lever@oracle.com>
Mon, 3 Jun 2024 14:35:02 +0000 (10:35 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Jun 2024 12:54:14 +0000 (14:54 +0200)
[ Upstream commit 3903902401451b1cd9d797a8c79769eb26ac7fe5 ]

The original implementation of nfsd used signals to stop threads during
shutdown.
In Linux 2.3.46pre5 nfsd gained the ability to shutdown threads
internally it if was asked to run "0" threads.  After this user-space
transitioned to using "rpc.nfsd 0" to stop nfsd and sending signals to
threads was no longer an important part of the API.

In commit 3ebdbe5203a8 ("SUNRPC: discard svo_setup and rename
svc_set_num_threads_sync()") (v5.17-rc1~75^2~41) we finally removed the
use of signals for stopping threads, using kthread_stop() instead.

This patch makes the "obvious" next step and removes the ability to
signal nfsd threads - or any svc threads.  nfsd stops allowing signals
and we don't check for their delivery any more.

This will allow for some simplification in later patches.

A change worth noting is in nfsd4_ssc_setup_dul().  There was previously
a signal_pending() check which would only succeed when the thread was
being shut down.  It should really have tested kthread_should_stop() as
well.  Now it just does the latter, not the former.

Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
[ cel: adjusted to apply to v5.10.y ]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/callback.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfssvc.c
net/sunrpc/svc_xprt.c

index 456af7d230cf180ec0b7d22dc1d498726ce70a7a..8fe143cad4a2bb442a1f1b8cea6d52ed64bd140a 100644 (file)
@@ -80,9 +80,6 @@ nfs4_callback_svc(void *vrqstp)
        set_freezable();
 
        while (!kthread_freezable_should_stop(NULL)) {
-
-               if (signal_pending(current))
-                       flush_signals(current);
                /*
                 * Listen for a request on the socket
                 */
@@ -112,11 +109,7 @@ nfs41_callback_svc(void *vrqstp)
        set_freezable();
 
        while (!kthread_freezable_should_stop(NULL)) {
-
-               if (signal_pending(current))
-                       flush_signals(current);
-
-               prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
+               prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_IDLE);
                spin_lock_bh(&serv->sv_cb_lock);
                if (!list_empty(&serv->sv_cb_list)) {
                        req = list_first_entry(&serv->sv_cb_list,
@@ -131,7 +124,7 @@ nfs41_callback_svc(void *vrqstp)
                } else {
                        spin_unlock_bh(&serv->sv_cb_lock);
                        if (!kthread_should_stop())
-                               schedule();
+                               freezable_schedule();
                        finish_wait(&serv->sv_cb_waitq, &wq);
                }
        }
index 9c51c10bcf08048c2fd1c4298464f7766ea67b88..8560a11daa47d1308f287884b2ca97a0ce9bd891 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/namei.h>
+#include <linux/freezer.h>
 
 #include <linux/sunrpc/addr.h>
 #include <linux/nfs_ssc.h>
@@ -1313,13 +1314,12 @@ try_again:
                /* found a match */
                if (ni->nsui_busy) {
                        /*  wait - and try again */
-                       prepare_to_wait(&nn->nfsd_ssc_waitq, &wait,
-                               TASK_INTERRUPTIBLE);
+                       prepare_to_wait(&nn->nfsd_ssc_waitq, &wait, TASK_IDLE);
                        spin_unlock(&nn->nfsd_ssc_lock);
 
                        /* allow 20secs for mount/unmount for now - revisit */
-                       if (signal_pending(current) ||
-                                       (schedule_timeout(20*HZ) == 0)) {
+                       if (kthread_should_stop() ||
+                                       (freezable_schedule_timeout(20*HZ) == 0)) {
                                finish_wait(&nn->nfsd_ssc_waitq, &wait);
                                kfree(work);
                                return nfserr_eagain;
index a0ecec54d3d7d5d406ff8ae5d7dc66208ae8c02c..8063fab2c0279c43e8ea458c12a391b31c397449 100644 (file)
@@ -952,15 +952,6 @@ nfsd(void *vrqstp)
 
        current->fs->umask = 0;
 
-       /*
-        * thread is spawned with all signals set to SIG_IGN, re-enable
-        * the ones that will bring down the thread
-        */
-       allow_signal(SIGKILL);
-       allow_signal(SIGHUP);
-       allow_signal(SIGINT);
-       allow_signal(SIGQUIT);
-
        atomic_inc(&nfsdstats.th_cnt);
 
        set_freezable();
@@ -985,9 +976,6 @@ nfsd(void *vrqstp)
                validate_process_creds();
        }
 
-       /* Clear signals before calling svc_exit_thread() */
-       flush_signals(current);
-
        atomic_dec(&nfsdstats.th_cnt);
 
 out:
index 000b737784bd901a89f808f53999fb75cbcd4aa5..d1eacf3358b81c119f0731415ae92e9c1d60bda8 100644 (file)
@@ -674,13 +674,13 @@ static int svc_alloc_arg(struct svc_rqst *rqstp)
                while (rqstp->rq_pages[i] == NULL) {
                        struct page *p = alloc_page(GFP_KERNEL);
                        if (!p) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               if (signalled() || kthread_should_stop()) {
+                               set_current_state(TASK_IDLE);
+                               if (kthread_should_stop()) {
                                        set_current_state(TASK_RUNNING);
                                        return -EINTR;
                                }
-                               schedule_timeout(msecs_to_jiffies(500));
                        }
+                       freezable_schedule_timeout(msecs_to_jiffies(500));
                        rqstp->rq_pages[i] = p;
                }
        rqstp->rq_page_end = &rqstp->rq_pages[i];
@@ -713,7 +713,7 @@ rqst_should_sleep(struct svc_rqst *rqstp)
                return false;
 
        /* are we shutting down? */
-       if (signalled() || kthread_should_stop())
+       if (kthread_should_stop())
                return false;
 
        /* are we freezing? */
@@ -735,18 +735,14 @@ static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
        if (rqstp->rq_xprt)
                goto out_found;
 
-       /*
-        * We have to be able to interrupt this wait
-        * to bring down the daemons ...
-        */
-       set_current_state(TASK_INTERRUPTIBLE);
+       set_current_state(TASK_IDLE);
        smp_mb__before_atomic();
        clear_bit(SP_CONGESTED, &pool->sp_flags);
        clear_bit(RQ_BUSY, &rqstp->rq_flags);
        smp_mb__after_atomic();
 
        if (likely(rqst_should_sleep(rqstp)))
-               time_left = schedule_timeout(timeout);
+               time_left = freezable_schedule_timeout(timeout);
        else
                __set_current_state(TASK_RUNNING);
 
@@ -761,7 +757,7 @@ static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
        if (!time_left)
                atomic_long_inc(&pool->sp_stats.threads_timedout);
 
-       if (signalled() || kthread_should_stop())
+       if (kthread_should_stop())
                return ERR_PTR(-EINTR);
        return ERR_PTR(-EAGAIN);
 out_found:
@@ -860,7 +856,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
        try_to_freeze();
        cond_resched();
        err = -EINTR;
-       if (signalled() || kthread_should_stop())
+       if (kthread_should_stop())
                goto out;
 
        xprt = svc_get_next_xprt(rqstp, timeout);