|
@@ -18,6 +18,7 @@
|
|
#include <linux/mm.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/module.h>
|
|
#include <linux/module.h>
|
|
|
|
+#include <linux/kthread.h>
|
|
|
|
|
|
#include <linux/sunrpc/types.h>
|
|
#include <linux/sunrpc/types.h>
|
|
#include <linux/sunrpc/xdr.h>
|
|
#include <linux/sunrpc/xdr.h>
|
|
@@ -291,15 +292,14 @@ svc_pool_map_put(void)
|
|
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Set the current thread's cpus_allowed mask so that it
|
|
|
|
|
|
+ * Set the given thread's cpus_allowed mask so that it
|
|
* will only run on cpus in the given pool.
|
|
* will only run on cpus in the given pool.
|
|
- *
|
|
|
|
- * Returns 1 and fills in oldmask iff a cpumask was applied.
|
|
|
|
*/
|
|
*/
|
|
-static inline int
|
|
|
|
-svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
|
|
|
|
|
|
+static inline void
|
|
|
|
+svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx)
|
|
{
|
|
{
|
|
struct svc_pool_map *m = &svc_pool_map;
|
|
struct svc_pool_map *m = &svc_pool_map;
|
|
|
|
+ unsigned int node = m->pool_to[pidx];
|
|
|
|
|
|
/*
|
|
/*
|
|
* The caller checks for sv_nrpools > 1, which
|
|
* The caller checks for sv_nrpools > 1, which
|
|
@@ -307,26 +307,17 @@ svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
|
|
*/
|
|
*/
|
|
BUG_ON(m->count == 0);
|
|
BUG_ON(m->count == 0);
|
|
|
|
|
|
- switch (m->mode)
|
|
|
|
- {
|
|
|
|
- default:
|
|
|
|
- return 0;
|
|
|
|
|
|
+ switch (m->mode) {
|
|
case SVC_POOL_PERCPU:
|
|
case SVC_POOL_PERCPU:
|
|
{
|
|
{
|
|
- unsigned int cpu = m->pool_to[pidx];
|
|
|
|
-
|
|
|
|
- *oldmask = current->cpus_allowed;
|
|
|
|
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
|
|
|
|
- return 1;
|
|
|
|
|
|
+ set_cpus_allowed_ptr(task, &cpumask_of_cpu(node));
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
case SVC_POOL_PERNODE:
|
|
case SVC_POOL_PERNODE:
|
|
{
|
|
{
|
|
- unsigned int node = m->pool_to[pidx];
|
|
|
|
node_to_cpumask_ptr(nodecpumask, node);
|
|
node_to_cpumask_ptr(nodecpumask, node);
|
|
-
|
|
|
|
- *oldmask = current->cpus_allowed;
|
|
|
|
- set_cpus_allowed_ptr(current, nodecpumask);
|
|
|
|
- return 1;
|
|
|
|
|
|
+ set_cpus_allowed_ptr(task, nodecpumask);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -578,47 +569,6 @@ out_enomem:
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(svc_prepare_thread);
|
|
EXPORT_SYMBOL(svc_prepare_thread);
|
|
|
|
|
|
-/*
|
|
|
|
- * Create a thread in the given pool. Caller must hold BKL or another lock to
|
|
|
|
- * serialize access to the svc_serv struct. On a NUMA or SMP machine, with a
|
|
|
|
- * multi-pool serv, the thread will be restricted to run on the cpus belonging
|
|
|
|
- * to the pool.
|
|
|
|
- */
|
|
|
|
-static int
|
|
|
|
-__svc_create_thread(svc_thread_fn func, struct svc_serv *serv,
|
|
|
|
- struct svc_pool *pool)
|
|
|
|
-{
|
|
|
|
- struct svc_rqst *rqstp;
|
|
|
|
- int error = -ENOMEM;
|
|
|
|
- int have_oldmask = 0;
|
|
|
|
- cpumask_t uninitialized_var(oldmask);
|
|
|
|
-
|
|
|
|
- rqstp = svc_prepare_thread(serv, pool);
|
|
|
|
- if (IS_ERR(rqstp)) {
|
|
|
|
- error = PTR_ERR(rqstp);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (serv->sv_nrpools > 1)
|
|
|
|
- have_oldmask = svc_pool_map_set_cpumask(pool->sp_id, &oldmask);
|
|
|
|
-
|
|
|
|
- error = kernel_thread((int (*)(void *)) func, rqstp, 0);
|
|
|
|
-
|
|
|
|
- if (have_oldmask)
|
|
|
|
- set_cpus_allowed(current, oldmask);
|
|
|
|
-
|
|
|
|
- if (error < 0)
|
|
|
|
- goto out_thread;
|
|
|
|
- svc_sock_update_bufs(serv);
|
|
|
|
- error = 0;
|
|
|
|
-out:
|
|
|
|
- return error;
|
|
|
|
-
|
|
|
|
-out_thread:
|
|
|
|
- svc_exit_thread(rqstp);
|
|
|
|
- goto out;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Choose a pool in which to create a new thread, for svc_set_num_threads
|
|
* Choose a pool in which to create a new thread, for svc_set_num_threads
|
|
*/
|
|
*/
|
|
@@ -688,7 +638,9 @@ found_pool:
|
|
int
|
|
int
|
|
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
|
|
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
|
|
{
|
|
{
|
|
- struct task_struct *victim;
|
|
|
|
|
|
+ struct svc_rqst *rqstp;
|
|
|
|
+ struct task_struct *task;
|
|
|
|
+ struct svc_pool *chosen_pool;
|
|
int error = 0;
|
|
int error = 0;
|
|
unsigned int state = serv->sv_nrthreads-1;
|
|
unsigned int state = serv->sv_nrthreads-1;
|
|
|
|
|
|
@@ -704,18 +656,34 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
|
|
/* create new threads */
|
|
/* create new threads */
|
|
while (nrservs > 0) {
|
|
while (nrservs > 0) {
|
|
nrservs--;
|
|
nrservs--;
|
|
|
|
+ chosen_pool = choose_pool(serv, pool, &state);
|
|
|
|
+
|
|
|
|
+ rqstp = svc_prepare_thread(serv, chosen_pool);
|
|
|
|
+ if (IS_ERR(rqstp)) {
|
|
|
|
+ error = PTR_ERR(rqstp);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
__module_get(serv->sv_module);
|
|
__module_get(serv->sv_module);
|
|
- error = __svc_create_thread(serv->sv_function, serv,
|
|
|
|
- choose_pool(serv, pool, &state));
|
|
|
|
- if (error < 0) {
|
|
|
|
|
|
+ task = kthread_create(serv->sv_function, rqstp, serv->sv_name);
|
|
|
|
+ if (IS_ERR(task)) {
|
|
|
|
+ error = PTR_ERR(task);
|
|
module_put(serv->sv_module);
|
|
module_put(serv->sv_module);
|
|
|
|
+ svc_exit_thread(rqstp);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ rqstp->rq_task = task;
|
|
|
|
+ if (serv->sv_nrpools > 1)
|
|
|
|
+ svc_pool_map_set_cpumask(task, chosen_pool->sp_id);
|
|
|
|
+
|
|
|
|
+ svc_sock_update_bufs(serv);
|
|
|
|
+ wake_up_process(task);
|
|
}
|
|
}
|
|
/* destroy old threads */
|
|
/* destroy old threads */
|
|
while (nrservs < 0 &&
|
|
while (nrservs < 0 &&
|
|
- (victim = choose_victim(serv, pool, &state)) != NULL) {
|
|
|
|
- send_sig(serv->sv_kill_signal, victim, 1);
|
|
|
|
|
|
+ (task = choose_victim(serv, pool, &state)) != NULL) {
|
|
|
|
+ send_sig(serv->sv_kill_signal, task, 1);
|
|
nrservs++;
|
|
nrservs++;
|
|
}
|
|
}
|
|
|
|
|