From: Chris Horn Date: Mon, 29 Jun 2015 18:38:14 +0000 (-0500) Subject: LU-6261 gnilnd: Add ability to bind scheduler threads to cpus. X-Git-Tag: 2.7.57~10 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=5a3c28358ce5bf48593494ca92ae0f1343a35332;p=fs%2Flustre-release.git LU-6261 gnilnd: Add ability to bind scheduler threads to cpus. Added the module parameter thread_affinity which when enabled, will bind the kgnilnd_sd_xx threads to cpus 1 through xx. thread_affinity defaults to disabled. Testing shows that enabling thread affinity will allow us to get better small message performance with more scheduler threads. Signed-off-by: Chris Horn Change-Id: I5298c25cc21a1a856e4d84f1bca4f484449cd055 Reviewed-on: http://review.whamcloud.com/15432 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: James Shimek Reviewed-by: Doug Oucharek Reviewed-by: Oleg Drokin --- diff --git a/lnet/klnds/gnilnd/gnilnd.c b/lnet/klnds/gnilnd/gnilnd.c index c911944..482b70e 100644 --- a/lnet/klnds/gnilnd/gnilnd.c +++ b/lnet/klnds/gnilnd/gnilnd.c @@ -42,6 +42,52 @@ lnd_t the_kgnilnd = { kgn_data_t kgnilnd_data; +int +kgnilnd_thread_start(int(*fn)(void *arg), void *arg, char *name, int id) +{ + struct task_struct *thrd; + + thrd = kthread_run(fn, arg, "%s_%02d", name, id); + if (IS_ERR(thrd)) + return PTR_ERR(thrd); + + atomic_inc(&kgnilnd_data.kgn_nthreads); + return 0; +} + +/* bind scheduler threads to cpus */ +int +kgnilnd_start_sd_threads(void) +{ + int cpu; + int i = 0; + struct task_struct *task; + + for_each_online_cpu(cpu) { + /* don't bind to cpu 0 - all interrupts are processed here */ + if (cpu == 0) + continue; + + task = kthread_create(kgnilnd_scheduler, (void *)((long)i), + "%s_%02d", "kgnilnd_sd", i); + if (!IS_ERR(task)) { + kthread_bind(task, cpu); + wake_up_process(task); + } else { + CERROR("Can't spawn gnilnd scheduler[%d] %ld\n", i, + PTR_ERR(task)); + return PTR_ERR(task); + } + atomic_inc(&kgnilnd_data.kgn_nthreads); + + if (++i >= *kgnilnd_tunables.kgn_sched_threads) { + break; + } + } + + return 0; +} + /* needs write_lock on kgn_peer_conn_lock */ int kgnilnd_close_stale_conns_locked(kgn_peer_t *peer, kgn_conn_t *newconn) @@ -2384,13 +2430,20 @@ int kgnilnd_base_startup(void) } /* threads will load balance across devs as they are available */ - for (i = 0; i < *kgnilnd_tunables.kgn_sched_threads; i++) { - rc = kgnilnd_thread_start(kgnilnd_scheduler, (void *)((long)i), - "kgnilnd_sd", i); - if (rc != 0) { - CERROR("Can't spawn gnilnd scheduler[%d]: %d\n", - i, rc); + if (*kgnilnd_tunables.kgn_thread_affinity) { + rc = kgnilnd_start_sd_threads(); + if (rc != 0) GOTO(failed, rc); + } else { + for (i = 0; i < *kgnilnd_tunables.kgn_sched_threads; i++) { + rc = kgnilnd_thread_start(kgnilnd_scheduler, + (void *)((long)i), + "kgnilnd_sd", i); + if (rc != 0) { + CERROR("Can't spawn gnilnd scheduler[%d]: %d\n", + i, rc); + GOTO(failed, rc); + } } } @@ -2421,8 +2474,6 @@ int kgnilnd_base_startup(void) } } - - /* flag everything initialised */ kgnilnd_data.kgn_init = GNILND_INIT_ALL; /*****************************************************/ diff --git a/lnet/klnds/gnilnd/gnilnd.h b/lnet/klnds/gnilnd/gnilnd.h index cb9c20b..a05ef82 100644 --- a/lnet/klnds/gnilnd/gnilnd.h +++ b/lnet/klnds/gnilnd/gnilnd.h @@ -482,6 +482,7 @@ typedef struct kgn_tunables { int *kgn_fast_reconn; /* fast reconnection on conn timeout */ int *kgn_efault_lbug; /* LBUG on receiving an EFAULT */ int *kgn_max_purgatory; /* # conns/peer to keep in purgatory */ + int *kgn_thread_affinity; /* bind scheduler threads to cpus */ #if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM cfs_sysctl_table_header_t *kgn_sysctl; /* sysctl interface */ #endif @@ -882,20 +883,9 @@ extern int _kgnilnd_schedule_conn(kgn_conn_t *conn, const char *caller, int line #define kgnilnd_schedule_conn(conn) \ _kgnilnd_schedule_conn(conn, __func__, __LINE__, 0); -#define kgnilnd_schedule_conn_refheld(conn, refheld) \ +#define kgnilnd_schedule_conn_refheld(conn, refheld) \ _kgnilnd_schedule_conn(conn, __func__, __LINE__, refheld); -static inline int -kgnilnd_thread_start(int(*fn)(void *arg), void *arg, char *name, int id) -{ - struct task_struct *thrd = kthread_run(fn, arg, "%s_%02d", name, id); - if (IS_ERR(thrd)) - return PTR_ERR(thrd); - - atomic_inc(&kgnilnd_data.kgn_nthreads); - return 0; -} - static inline void kgnilnd_thread_fini(void) { @@ -1773,6 +1763,7 @@ int kgnilnd_reaper(void *arg); int kgnilnd_scheduler(void *arg); int kgnilnd_dgram_mover(void *arg); int kgnilnd_rca(void *arg); +int kgnilnd_thread_start(int(*fn)(void *arg), void *arg, char *name, int id); int kgnilnd_create_conn(kgn_conn_t **connp, kgn_device_t *dev); int kgnilnd_conn_isdup_locked(kgn_peer_t *peer, kgn_conn_t *newconn); diff --git a/lnet/klnds/gnilnd/gnilnd_modparams.c b/lnet/klnds/gnilnd/gnilnd_modparams.c index 7d1c39f..d8e8d87 100644 --- a/lnet/klnds/gnilnd/gnilnd_modparams.c +++ b/lnet/klnds/gnilnd/gnilnd_modparams.c @@ -187,6 +187,10 @@ static int max_conn_purg = GNILND_PURGATORY_MAX; CFS_MODULE_PARM(max_conn_purg, "i", int, 0644, "Max number of connections per peer in purgatory"); +static int thread_affinity = 0; +CFS_MODULE_PARM(thread_affinity, "i", int, 0444, + "scheduler thread affinity default 0 (diabled)"); + kgn_tunables_t kgnilnd_tunables = { .kgn_min_reconnect_interval = &min_reconnect_interval, .kgn_max_reconnect_interval = &max_reconnect_interval, @@ -224,6 +228,7 @@ kgn_tunables_t kgnilnd_tunables = { .kgn_eager_credits = &eager_credits, .kgn_fast_reconn = &fast_reconn, .kgn_efault_lbug = &efault_lbug, + .kgn_thread_affinity = &thread_affinity, .kgn_max_purgatory = &max_conn_purg }; @@ -510,6 +515,14 @@ static struct ctl_table kgnilnd_ctl_table[] = { }, { INIT_CTL_NAME + .procname = "thread_affinity" + .data = &thread_affinity, + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec + }, + { + INIT_CTL_NAME .procname = "max_conn_purg" .data = &max_conn_purg, .maxlen = sizeof(int),