Skip to content

Commit ed6473d

Browse files
trondmypdJ. Bruce Fields
authored andcommitted
NFSv4: Fix callback server shutdown
We want to use kthread_stop() in order to ensure the threads are shut down before we tear down the nfs_callback_info in nfs_callback_down. Tested-and-reviewed-by: Kinglong Mee <kinglongmee@gmail.com> Reported-by: Kinglong Mee <kinglongmee@gmail.com> Fixes: bb6aeba ("NFSv4.x: Switch to using svc_set_num_threads()...") Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 9e0d876 commit ed6473d

File tree

3 files changed

+55
-8
lines changed

3 files changed

+55
-8
lines changed

fs/nfs/callback.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ nfs4_callback_svc(void *vrqstp)
7676

7777
set_freezable();
7878

79-
while (!kthread_should_stop()) {
79+
while (!kthread_freezable_should_stop(NULL)) {
80+
81+
if (signal_pending(current))
82+
flush_signals(current);
8083
/*
8184
* Listen for a request on the socket
8285
*/
@@ -85,6 +88,8 @@ nfs4_callback_svc(void *vrqstp)
8588
continue;
8689
svc_process(rqstp);
8790
}
91+
svc_exit_thread(rqstp);
92+
module_put_and_exit(0);
8893
return 0;
8994
}
9095

@@ -103,9 +108,10 @@ nfs41_callback_svc(void *vrqstp)
103108

104109
set_freezable();
105110

106-
while (!kthread_should_stop()) {
107-
if (try_to_freeze())
108-
continue;
111+
while (!kthread_freezable_should_stop(NULL)) {
112+
113+
if (signal_pending(current))
114+
flush_signals(current);
109115

110116
prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
111117
spin_lock_bh(&serv->sv_cb_lock);
@@ -121,11 +127,13 @@ nfs41_callback_svc(void *vrqstp)
121127
error);
122128
} else {
123129
spin_unlock_bh(&serv->sv_cb_lock);
124-
schedule();
130+
if (!kthread_should_stop())
131+
schedule();
125132
finish_wait(&serv->sv_cb_waitq, &wq);
126133
}
127-
flush_signals(current);
128134
}
135+
svc_exit_thread(rqstp);
136+
module_put_and_exit(0);
129137
return 0;
130138
}
131139

@@ -221,14 +229,14 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
221229
static struct svc_serv_ops nfs40_cb_sv_ops = {
222230
.svo_function = nfs4_callback_svc,
223231
.svo_enqueue_xprt = svc_xprt_do_enqueue,
224-
.svo_setup = svc_set_num_threads,
232+
.svo_setup = svc_set_num_threads_sync,
225233
.svo_module = THIS_MODULE,
226234
};
227235
#if defined(CONFIG_NFS_V4_1)
228236
static struct svc_serv_ops nfs41_cb_sv_ops = {
229237
.svo_function = nfs41_callback_svc,
230238
.svo_enqueue_xprt = svc_xprt_do_enqueue,
231-
.svo_setup = svc_set_num_threads,
239+
.svo_setup = svc_set_num_threads_sync,
232240
.svo_module = THIS_MODULE,
233241
};
234242

include/linux/sunrpc/svc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ void svc_pool_map_put(void);
473473
struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
474474
struct svc_serv_ops *);
475475
int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
476+
int svc_set_num_threads_sync(struct svc_serv *, struct svc_pool *, int);
476477
int svc_pool_stats_open(struct svc_serv *serv, struct file *file);
477478
void svc_destroy(struct svc_serv *);
478479
void svc_shutdown_net(struct svc_serv *, struct net *);

net/sunrpc/svc.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,44 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
795795
}
796796
EXPORT_SYMBOL_GPL(svc_set_num_threads);
797797

798+
/* destroy old threads */
799+
static int
800+
svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
801+
{
802+
struct task_struct *task;
803+
unsigned int state = serv->sv_nrthreads-1;
804+
805+
/* destroy old threads */
806+
do {
807+
task = choose_victim(serv, pool, &state);
808+
if (task == NULL)
809+
break;
810+
kthread_stop(task);
811+
nrservs++;
812+
} while (nrservs < 0);
813+
return 0;
814+
}
815+
816+
int
817+
svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
818+
{
819+
if (pool == NULL) {
820+
/* The -1 assumes caller has done a svc_get() */
821+
nrservs -= (serv->sv_nrthreads-1);
822+
} else {
823+
spin_lock_bh(&pool->sp_lock);
824+
nrservs -= pool->sp_nrthreads;
825+
spin_unlock_bh(&pool->sp_lock);
826+
}
827+
828+
if (nrservs > 0)
829+
return svc_start_kthreads(serv, pool, nrservs);
830+
if (nrservs < 0)
831+
return svc_stop_kthreads(serv, pool, nrservs);
832+
return 0;
833+
}
834+
EXPORT_SYMBOL_GPL(svc_set_num_threads_sync);
835+
798836
/*
799837
* Called from a server thread as it's exiting. Caller must hold the "service
800838
* mutex" for the service.

0 commit comments

Comments
 (0)