Commit 9e0d8768 authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields

SUNRPC: Refactor svc_set_num_threads()

Refactor to separate out the functions of starting and stopping threads
so that they can be used in other helpers.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Tested-and-reviewed-by: default avatarKinglong Mee <kinglongmee@gmail.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent df807fff
...@@ -702,59 +702,32 @@ choose_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state) ...@@ -702,59 +702,32 @@ choose_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state)
return task; return task;
} }
/* /* create new threads */
* Create or destroy enough new threads to make the number static int
* of threads the given number. If `pool' is non-NULL, applies svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
* only to threads in that pool, otherwise round-robins between
* all pools. Caller must ensure that mutual exclusion between this and
* server startup or shutdown.
*
* Destroying threads relies on the service threads filling in
* rqstp->rq_task, which only the nfs ones do. Assumes the serv
* has been created using svc_create_pooled().
*
* Based on code that used to be in nfsd_svc() but tweaked
* to be pool-aware.
*/
int
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
{ {
struct svc_rqst *rqstp; struct svc_rqst *rqstp;
struct task_struct *task; struct task_struct *task;
struct svc_pool *chosen_pool; struct svc_pool *chosen_pool;
int error = 0;
unsigned int state = serv->sv_nrthreads-1; unsigned int state = serv->sv_nrthreads-1;
int node; int node;
if (pool == NULL) { do {
/* The -1 assumes caller has done a svc_get() */
nrservs -= (serv->sv_nrthreads-1);
} else {
spin_lock_bh(&pool->sp_lock);
nrservs -= pool->sp_nrthreads;
spin_unlock_bh(&pool->sp_lock);
}
/* create new threads */
while (nrservs > 0) {
nrservs--; nrservs--;
chosen_pool = choose_pool(serv, pool, &state); chosen_pool = choose_pool(serv, pool, &state);
node = svc_pool_map_get_node(chosen_pool->sp_id); node = svc_pool_map_get_node(chosen_pool->sp_id);
rqstp = svc_prepare_thread(serv, chosen_pool, node); rqstp = svc_prepare_thread(serv, chosen_pool, node);
if (IS_ERR(rqstp)) { if (IS_ERR(rqstp))
error = PTR_ERR(rqstp); return PTR_ERR(rqstp);
break;
}
__module_get(serv->sv_ops->svo_module); __module_get(serv->sv_ops->svo_module);
task = kthread_create_on_node(serv->sv_ops->svo_function, rqstp, task = kthread_create_on_node(serv->sv_ops->svo_function, rqstp,
node, "%s", serv->sv_name); node, "%s", serv->sv_name);
if (IS_ERR(task)) { if (IS_ERR(task)) {
error = PTR_ERR(task);
module_put(serv->sv_ops->svo_module); module_put(serv->sv_ops->svo_module);
svc_exit_thread(rqstp); svc_exit_thread(rqstp);
break; return PTR_ERR(task);
} }
rqstp->rq_task = task; rqstp->rq_task = task;
...@@ -763,15 +736,62 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) ...@@ -763,15 +736,62 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
svc_sock_update_bufs(serv); svc_sock_update_bufs(serv);
wake_up_process(task); wake_up_process(task);
} } while (nrservs > 0);
return 0;
}
/* destroy old threads */
static int
svc_signal_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
{
struct task_struct *task;
unsigned int state = serv->sv_nrthreads-1;
/* destroy old threads */ /* destroy old threads */
while (nrservs < 0 && do {
(task = choose_victim(serv, pool, &state)) != NULL) { task = choose_victim(serv, pool, &state);
if (task == NULL)
break;
send_sig(SIGINT, task, 1); send_sig(SIGINT, task, 1);
nrservs++; nrservs++;
} while (nrservs < 0);
return 0;
}
/*
* Create or destroy enough new threads to make the number
* of threads the given number. If `pool' is non-NULL, applies
* only to threads in that pool, otherwise round-robins between
* all pools. Caller must ensure that mutual exclusion between this and
* server startup or shutdown.
*
* Destroying threads relies on the service threads filling in
* rqstp->rq_task, which only the nfs ones do. Assumes the serv
* has been created using svc_create_pooled().
*
* Based on code that used to be in nfsd_svc() but tweaked
* to be pool-aware.
*/
int
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
{
if (pool == NULL) {
/* The -1 assumes caller has done a svc_get() */
nrservs -= (serv->sv_nrthreads-1);
} else {
spin_lock_bh(&pool->sp_lock);
nrservs -= pool->sp_nrthreads;
spin_unlock_bh(&pool->sp_lock);
} }
return error; if (nrservs > 0)
return svc_start_kthreads(serv, pool, nrservs);
if (nrservs < 0)
return svc_signal_kthreads(serv, pool, nrservs);
return 0;
} }
EXPORT_SYMBOL_GPL(svc_set_num_threads); EXPORT_SYMBOL_GPL(svc_set_num_threads);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment