[PATCH v2 10/25] staging: lustre: libcfs: use distance in cpu and node handling

2018-05-29 Thread James Simmons
From: Amir Shehata 

Take into consideration the location of NUMA nodes and core
when calling cfs_cpt_[un]set_cpu() and cfs_cpt_[un]set_node().
This enables functioning on platforms with 100s of cores and
NUMA nodes.

Signed-off-by: Amir Shehata 
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7734
Reviewed-on: http://review.whamcloud.com/18916
Reviewed-by: Olaf Weber 
Reviewed-by: Doug Oucharek 
Signed-off-by: James Simmons 
---
Changelog:

v1) Initial patch
v2) Rebased patch to handle recent libcfs changes

 drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c | 192 ++--
 1 file changed, 143 insertions(+), 49 deletions(-)

diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c 
b/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
index 2a74e51..9ff9fe9 100644
--- a/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
+++ b/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
@@ -330,11 +330,134 @@ unsigned int cfs_cpt_distance(struct cfs_cpt_table 
*cptab, int cpt1, int cpt2)
 }
 EXPORT_SYMBOL(cfs_cpt_distance);
 
+/*
+ * Calculate the maximum NUMA distance between all nodes in the
+ * from_mask and all nodes in the to_mask.
+ */
+static unsigned int cfs_cpt_distance_calculate(nodemask_t *from_mask,
+  nodemask_t *to_mask)
+{
+   unsigned int maximum;
+   unsigned int distance;
+   int from;
+   int to;
+
+   maximum = 0;
+   for_each_node_mask(from, *from_mask) {
+   for_each_node_mask(to, *to_mask) {
+   distance = node_distance(from, to);
+   if (maximum < distance)
+   maximum = distance;
+   }
+   }
+   return maximum;
+}
+
+static void cfs_cpt_add_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
+{
+   cptab->ctb_cpu2cpt[cpu] = cpt;
+
+   cpumask_set_cpu(cpu, cptab->ctb_cpumask);
+   cpumask_set_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask);
+}
+
+static void cfs_cpt_del_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
+{
+   cpumask_clear_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask);
+   cpumask_clear_cpu(cpu, cptab->ctb_cpumask);
+
+   cptab->ctb_cpu2cpt[cpu] = -1;
+}
+
+static void cfs_cpt_add_node(struct cfs_cpt_table *cptab, int cpt, int node)
+{
+   struct cfs_cpu_partition *part;
+
+   if (!node_isset(node, *cptab->ctb_nodemask)) {
+   unsigned int dist;
+
+   /* first time node is added to the CPT table */
+   node_set(node, *cptab->ctb_nodemask);
+   cptab->ctb_node2cpt[node] = cpt;
+
+   dist = cfs_cpt_distance_calculate(cptab->ctb_nodemask,
+ cptab->ctb_nodemask);
+   cptab->ctb_distance = dist;
+   }
+
+   part = >ctb_parts[cpt];
+   if (!node_isset(node, *part->cpt_nodemask)) {
+   int cpt2;
+
+   /* first time node is added to this CPT */
+   node_set(node, *part->cpt_nodemask);
+   for (cpt2 = 0; cpt2 < cptab->ctb_nparts; cpt2++) {
+   struct cfs_cpu_partition *part2;
+   unsigned int dist;
+
+   part2 = >ctb_parts[cpt2];
+   dist = cfs_cpt_distance_calculate(part->cpt_nodemask,
+ part2->cpt_nodemask);
+   part->cpt_distance[cpt2] = dist;
+   dist = cfs_cpt_distance_calculate(part2->cpt_nodemask,
+ part->cpt_nodemask);
+   part2->cpt_distance[cpt] = dist;
+   }
+   }
+}
+
+static void cfs_cpt_del_node(struct cfs_cpt_table *cptab, int cpt, int node)
+{
+   struct cfs_cpu_partition *part = >ctb_parts[cpt];
+   int cpu;
+
+   for_each_cpu(cpu, part->cpt_cpumask) {
+   /* this CPT has other CPU belonging to this node? */
+   if (cpu_to_node(cpu) == node)
+   break;
+   }
+
+   if (cpu >= nr_cpu_ids && node_isset(node,  *part->cpt_nodemask)) {
+   int cpt2;
+
+   /* No more CPUs in the node for this CPT. */
+   node_clear(node, *part->cpt_nodemask);
+   for (cpt2 = 0; cpt2 < cptab->ctb_nparts; cpt2++) {
+   struct cfs_cpu_partition *part2;
+   unsigned int dist;
+
+   part2 = >ctb_parts[cpt2];
+   if (node_isset(node, *part2->cpt_nodemask))
+   cptab->ctb_node2cpt[node] = cpt2;
+
+   dist = cfs_cpt_distance_calculate(part->cpt_nodemask,
+ part2->cpt_nodemask);
+   part->cpt_distance[cpt2] = dist;
+   dist = cfs_cpt_distance_calculate(part2->cpt_nodemask,
+

[PATCH v2 10/25] staging: lustre: libcfs: use distance in cpu and node handling

2018-05-29 Thread James Simmons
From: Amir Shehata 

Take into consideration the location of NUMA nodes and core
when calling cfs_cpt_[un]set_cpu() and cfs_cpt_[un]set_node().
This enables functioning on platforms with 100s of cores and
NUMA nodes.

Signed-off-by: Amir Shehata 
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7734
Reviewed-on: http://review.whamcloud.com/18916
Reviewed-by: Olaf Weber 
Reviewed-by: Doug Oucharek 
Signed-off-by: James Simmons 
---
Changelog:

v1) Initial patch
v2) Rebased patch to handle recent libcfs changes

 drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c | 192 ++--
 1 file changed, 143 insertions(+), 49 deletions(-)

diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c 
b/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
index 2a74e51..9ff9fe9 100644
--- a/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
+++ b/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
@@ -330,11 +330,134 @@ unsigned int cfs_cpt_distance(struct cfs_cpt_table 
*cptab, int cpt1, int cpt2)
 }
 EXPORT_SYMBOL(cfs_cpt_distance);
 
+/*
+ * Calculate the maximum NUMA distance between all nodes in the
+ * from_mask and all nodes in the to_mask.
+ */
+static unsigned int cfs_cpt_distance_calculate(nodemask_t *from_mask,
+  nodemask_t *to_mask)
+{
+   unsigned int maximum;
+   unsigned int distance;
+   int from;
+   int to;
+
+   maximum = 0;
+   for_each_node_mask(from, *from_mask) {
+   for_each_node_mask(to, *to_mask) {
+   distance = node_distance(from, to);
+   if (maximum < distance)
+   maximum = distance;
+   }
+   }
+   return maximum;
+}
+
+static void cfs_cpt_add_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
+{
+   cptab->ctb_cpu2cpt[cpu] = cpt;
+
+   cpumask_set_cpu(cpu, cptab->ctb_cpumask);
+   cpumask_set_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask);
+}
+
+static void cfs_cpt_del_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
+{
+   cpumask_clear_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask);
+   cpumask_clear_cpu(cpu, cptab->ctb_cpumask);
+
+   cptab->ctb_cpu2cpt[cpu] = -1;
+}
+
+static void cfs_cpt_add_node(struct cfs_cpt_table *cptab, int cpt, int node)
+{
+   struct cfs_cpu_partition *part;
+
+   if (!node_isset(node, *cptab->ctb_nodemask)) {
+   unsigned int dist;
+
+   /* first time node is added to the CPT table */
+   node_set(node, *cptab->ctb_nodemask);
+   cptab->ctb_node2cpt[node] = cpt;
+
+   dist = cfs_cpt_distance_calculate(cptab->ctb_nodemask,
+ cptab->ctb_nodemask);
+   cptab->ctb_distance = dist;
+   }
+
+   part = >ctb_parts[cpt];
+   if (!node_isset(node, *part->cpt_nodemask)) {
+   int cpt2;
+
+   /* first time node is added to this CPT */
+   node_set(node, *part->cpt_nodemask);
+   for (cpt2 = 0; cpt2 < cptab->ctb_nparts; cpt2++) {
+   struct cfs_cpu_partition *part2;
+   unsigned int dist;
+
+   part2 = >ctb_parts[cpt2];
+   dist = cfs_cpt_distance_calculate(part->cpt_nodemask,
+ part2->cpt_nodemask);
+   part->cpt_distance[cpt2] = dist;
+   dist = cfs_cpt_distance_calculate(part2->cpt_nodemask,
+ part->cpt_nodemask);
+   part2->cpt_distance[cpt] = dist;
+   }
+   }
+}
+
+static void cfs_cpt_del_node(struct cfs_cpt_table *cptab, int cpt, int node)
+{
+   struct cfs_cpu_partition *part = >ctb_parts[cpt];
+   int cpu;
+
+   for_each_cpu(cpu, part->cpt_cpumask) {
+   /* this CPT has other CPU belonging to this node? */
+   if (cpu_to_node(cpu) == node)
+   break;
+   }
+
+   if (cpu >= nr_cpu_ids && node_isset(node,  *part->cpt_nodemask)) {
+   int cpt2;
+
+   /* No more CPUs in the node for this CPT. */
+   node_clear(node, *part->cpt_nodemask);
+   for (cpt2 = 0; cpt2 < cptab->ctb_nparts; cpt2++) {
+   struct cfs_cpu_partition *part2;
+   unsigned int dist;
+
+   part2 = >ctb_parts[cpt2];
+   if (node_isset(node, *part2->cpt_nodemask))
+   cptab->ctb_node2cpt[node] = cpt2;
+
+   dist = cfs_cpt_distance_calculate(part->cpt_nodemask,
+ part2->cpt_nodemask);
+   part->cpt_distance[cpt2] = dist;
+   dist = cfs_cpt_distance_calculate(part2->cpt_nodemask,
+