[PATCH 23/25] staging: lustre: libcfs: rework CPU pattern parsing code

2018-04-15 Thread James Simmons
From: Dmitry Eremin 

Currently the module param string for CPU pattern can be
modified which is wrong. Rewrite CPU pattern parsing code
to avoid the passed buffer from being changed. This change
also enables us to add real errors propogation to the caller
functions.

Signed-off-by: Dmitry Eremin 
Signed-off-by: Amir Shehata 
Signed-off-by: Andreas Dilger 
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8703
Reviewed-on: https://review.whamcloud.com/23306
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-9715
Reviewed-on: https://review.whamcloud.com/27872
Reviewed-by: James Simmons 
Reviewed-by: Andreas Dilger 
Reviewed-by: Patrick Farrell 
Reviewed-by: Olaf Weber 
Reviewed-by: Oleg Drokin 
Signed-off-by: James Simmons 
---
 .../staging/lustre/lnet/libcfs/linux/linux-cpu.c   | 151 -
 1 file changed, 88 insertions(+), 63 deletions(-)

diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c 
b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
index a08816a..915cfca 100644
--- a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
+++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
@@ -662,11 +662,11 @@ int cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt)
nodemask = cptab->ctb_parts[cpt].cpt_nodemask;
}
 
-   if (cpumask_any_and(*cpumask, cpu_online_mask) >= nr_cpu_ids) {
+   if (!cpumask_intersects(*cpumask, cpu_online_mask)) {
CDEBUG(D_INFO,
   "No online CPU found in CPU partition %d, did someone do 
CPU hotplug on system? You might need to reload Lustre modules to keep system 
working well.\n",
   cpt);
-   return -EINVAL;
+   return -ENODEV;
}
 
for_each_online_cpu(cpu) {
@@ -830,11 +830,13 @@ static struct cfs_cpt_table *cfs_cpt_table_create(int 
ncpt)
cptab = cfs_cpt_table_alloc(ncpt);
if (!cptab) {
CERROR("Failed to allocate CPU map(%d)\n", ncpt);
+   rc = -ENOMEM;
goto failed;
}
 
if (!zalloc_cpumask_var(_mask, GFP_NOFS)) {
CERROR("Failed to allocate scratch cpumask\n");
+   rc = -ENOMEM;
goto failed;
}
 
@@ -849,8 +851,10 @@ static struct cfs_cpt_table *cfs_cpt_table_create(int ncpt)
 
rc = cfs_cpt_choose_ncpus(cptab, cpt, node_mask,
  num - ncpu);
-   if (rc < 0)
+   if (rc < 0) {
+   rc = -EINVAL;
goto failed_mask;
+   }
 
ncpu = cpumask_weight(part->cpt_cpumask);
if (ncpu == num + !!(rem > 0)) {
@@ -873,37 +877,51 @@ static struct cfs_cpt_table *cfs_cpt_table_create(int 
ncpt)
if (cptab)
cfs_cpt_table_free(cptab);
 
-   return NULL;
+   return ERR_PTR(rc);
 }
 
-static struct cfs_cpt_table *cfs_cpt_table_create_pattern(char *pattern)
+static struct cfs_cpt_table *cfs_cpt_table_create_pattern(const char *pattern)
 {
struct cfs_cpt_table *cptab;
+   char *pattern_dup;
+   char *bracket;
char *str;
int node = 0;
-   int high;
int ncpt = 0;
-   int cpt;
+   int cpt = 0;
+   int high;
int rc;
int c;
int i;
 
-   str = strim(pattern);
+   pattern_dup = kstrdup(pattern, GFP_KERNEL);
+   if (!pattern_dup) {
+   CERROR("Failed to duplicate pattern '%s'\n", pattern);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   str = strim(pattern_dup);
if (*str == 'n' || *str == 'N') {
-   pattern = str + 1;
-   if (*pattern != '\0') {
-   node = 1;
-   } else { /* shortcut to create CPT from NUMA & CPU topology */
+   str++; /* skip 'N' char */
+   node = 1; /* NUMA pattern */
+   if (*str == '\0') {
node = -1;
-   ncpt = num_online_nodes();
+   for_each_online_node(i) {
+   if (!cpumask_empty(cpumask_of_node(i)))
+   ncpt++;
+   }
+   if (ncpt == 1) { /* single NUMA node */
+   kfree(pattern_dup);
+   return cfs_cpt_table_create(cpu_npartitions);
+   }
}
}
 
if (!ncpt) { /* scanning bracket which is mark of partition */
-   for (str = pattern;; str++, ncpt++) {
-   str = strchr(str, '[');
-   

[PATCH 23/25] staging: lustre: libcfs: rework CPU pattern parsing code

2018-04-15 Thread James Simmons
From: Dmitry Eremin 

Currently the module param string for CPU pattern can be
modified which is wrong. Rewrite CPU pattern parsing code
to avoid the passed buffer from being changed. This change
also enables us to add real errors propogation to the caller
functions.

Signed-off-by: Dmitry Eremin 
Signed-off-by: Amir Shehata 
Signed-off-by: Andreas Dilger 
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8703
Reviewed-on: https://review.whamcloud.com/23306
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-9715
Reviewed-on: https://review.whamcloud.com/27872
Reviewed-by: James Simmons 
Reviewed-by: Andreas Dilger 
Reviewed-by: Patrick Farrell 
Reviewed-by: Olaf Weber 
Reviewed-by: Oleg Drokin 
Signed-off-by: James Simmons 
---
 .../staging/lustre/lnet/libcfs/linux/linux-cpu.c   | 151 -
 1 file changed, 88 insertions(+), 63 deletions(-)

diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c 
b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
index a08816a..915cfca 100644
--- a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
+++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
@@ -662,11 +662,11 @@ int cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt)
nodemask = cptab->ctb_parts[cpt].cpt_nodemask;
}
 
-   if (cpumask_any_and(*cpumask, cpu_online_mask) >= nr_cpu_ids) {
+   if (!cpumask_intersects(*cpumask, cpu_online_mask)) {
CDEBUG(D_INFO,
   "No online CPU found in CPU partition %d, did someone do 
CPU hotplug on system? You might need to reload Lustre modules to keep system 
working well.\n",
   cpt);
-   return -EINVAL;
+   return -ENODEV;
}
 
for_each_online_cpu(cpu) {
@@ -830,11 +830,13 @@ static struct cfs_cpt_table *cfs_cpt_table_create(int 
ncpt)
cptab = cfs_cpt_table_alloc(ncpt);
if (!cptab) {
CERROR("Failed to allocate CPU map(%d)\n", ncpt);
+   rc = -ENOMEM;
goto failed;
}
 
if (!zalloc_cpumask_var(_mask, GFP_NOFS)) {
CERROR("Failed to allocate scratch cpumask\n");
+   rc = -ENOMEM;
goto failed;
}
 
@@ -849,8 +851,10 @@ static struct cfs_cpt_table *cfs_cpt_table_create(int ncpt)
 
rc = cfs_cpt_choose_ncpus(cptab, cpt, node_mask,
  num - ncpu);
-   if (rc < 0)
+   if (rc < 0) {
+   rc = -EINVAL;
goto failed_mask;
+   }
 
ncpu = cpumask_weight(part->cpt_cpumask);
if (ncpu == num + !!(rem > 0)) {
@@ -873,37 +877,51 @@ static struct cfs_cpt_table *cfs_cpt_table_create(int 
ncpt)
if (cptab)
cfs_cpt_table_free(cptab);
 
-   return NULL;
+   return ERR_PTR(rc);
 }
 
-static struct cfs_cpt_table *cfs_cpt_table_create_pattern(char *pattern)
+static struct cfs_cpt_table *cfs_cpt_table_create_pattern(const char *pattern)
 {
struct cfs_cpt_table *cptab;
+   char *pattern_dup;
+   char *bracket;
char *str;
int node = 0;
-   int high;
int ncpt = 0;
-   int cpt;
+   int cpt = 0;
+   int high;
int rc;
int c;
int i;
 
-   str = strim(pattern);
+   pattern_dup = kstrdup(pattern, GFP_KERNEL);
+   if (!pattern_dup) {
+   CERROR("Failed to duplicate pattern '%s'\n", pattern);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   str = strim(pattern_dup);
if (*str == 'n' || *str == 'N') {
-   pattern = str + 1;
-   if (*pattern != '\0') {
-   node = 1;
-   } else { /* shortcut to create CPT from NUMA & CPU topology */
+   str++; /* skip 'N' char */
+   node = 1; /* NUMA pattern */
+   if (*str == '\0') {
node = -1;
-   ncpt = num_online_nodes();
+   for_each_online_node(i) {
+   if (!cpumask_empty(cpumask_of_node(i)))
+   ncpt++;
+   }
+   if (ncpt == 1) { /* single NUMA node */
+   kfree(pattern_dup);
+   return cfs_cpt_table_create(cpu_npartitions);
+   }
}
}
 
if (!ncpt) { /* scanning bracket which is mark of partition */
-   for (str = pattern;; str++, ncpt++) {
-   str = strchr(str, '[');
-   if (!str)
-   break;
+   bracket = str;
+   while ((bracket = strchr(bracket, '['))) {
+   bracket++;
+   ncpt++;
}