Whamcloud - gitweb
LU-6261 gnilnd: Add ability to bind scheduler threads to cpus. 32/15432/2
authorChris Horn <hornc@cray.com>
Mon, 29 Jun 2015 18:38:14 +0000 (13:38 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 25 Jul 2015 03:07:28 +0000 (03:07 +0000)
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 <hornc@cray.com>
Change-Id: I5298c25cc21a1a856e4d84f1bca4f484449cd055
Reviewed-on: http://review.whamcloud.com/15432
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: James Shimek <jshimek@cray.com>
Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lnet/klnds/gnilnd/gnilnd.c
lnet/klnds/gnilnd/gnilnd.h
lnet/klnds/gnilnd/gnilnd_modparams.c

index c911944..482b70e 100644 (file)
@@ -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;
        /*****************************************************/
index cb9c20b..a05ef82 100644 (file)
@@ -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);
index 7d1c39f..d8e8d87 100644 (file)
@@ -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),