Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3447307imm; Tue, 29 May 2018 07:25:36 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrBOvf47B4MtB6uAMw9SsK7QaTlx07aAzYJqsqm1mVjUIGsi+ncvDrc7p+ScK9/2uIoBNdd X-Received: by 2002:a17:902:8a95:: with SMTP id p21-v6mr18092470plo.325.1527603936863; Tue, 29 May 2018 07:25:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527603936; cv=none; d=google.com; s=arc-20160816; b=1FFCaL8RxU3etUcc9j6s+Og2tNCBg8pt02mYbILhzgrb0wR0rqejG8WC1UDq5u0EeG 0P3T0tc2DowSGJd0aEv5tLftxVgFl9gJuAfqXv3+zMzCwEypr0yvf+f/eowDf7zg7q4i G7rPNa8Ldt22at0LL0PZFdK6USG8u9RF6lP+mUHkm7zXRyRrT28cbjsLEjxJZTpXZKNm kD2IGr+S4dYS7RSaH4qohQS84d0USqnocZj0+h0AUP2zrr0bMGNJmnUo6QJXdgsd/DL5 XCVIk4vJOlxOTg8j84ClC2dPG+ZnwHiFeiySFhr44WvynQ/gUogkJQN17izQIAL+wPMy WUzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=rzxG8pQ+A2x7/IGL294ZVz/S5/4E27d96RuQBWOtktk=; b=Vil6RfvxxERtzkjvOAaETZVMOaknkvyipVM9NZYL45XNDRFweCb8bwkHvUkxCK6zBZ W9ttSwigiF7zxyx6mFb/5+nnGnP6Nx9sGOnaAYU/9Z6e9FBLWQccD3WWziwSvljABvum yeboL1IWoehEnyetJiuQzpjlN//JWVR4W+aBc3w+xVn0VvHQPvQtSyLY+NhUbLHRC1q9 tsiqrWdBfWaARRtNkSCg2inFgxXOCFYCFm5wT6i67DvORJHL+Tc0hdBqPzHT7pQhp8va MAVcW3pk+cSX6wjttpyl/AG/sgAvjwcIxLdqgX3U7eJpRxEtDJwJqX7jdmCAV94IZKHa 3Psg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c8-v6si32730179pfj.138.2018.05.29.07.24.52; Tue, 29 May 2018 07:25:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935337AbeE2OWv (ORCPT + 99 others); Tue, 29 May 2018 10:22:51 -0400 Received: from smtp4.ccs.ornl.gov ([160.91.203.40]:38208 "EHLO smtp4.ccs.ornl.gov" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935249AbeE2OWm (ORCPT ); Tue, 29 May 2018 10:22:42 -0400 Received: from star.ccs.ornl.gov (star.ccs.ornl.gov [160.91.202.134]) by smtp4.ccs.ornl.gov (Postfix) with ESMTP id 10E3E10052D7; Tue, 29 May 2018 10:22:07 -0400 (EDT) Received: by star.ccs.ornl.gov (Postfix, from userid 2004) id 0E5532C1; Tue, 29 May 2018 10:22:07 -0400 (EDT) From: James Simmons To: Greg Kroah-Hartman , devel@driverdev.osuosl.org, Andreas Dilger , Oleg Drokin , NeilBrown Cc: Linux Kernel Mailing List , Lustre Development List , Dmitry Eremin , Amir Shehata , James Simmons Subject: [PATCH v2 23/25] staging: lustre: libcfs: rework CPU pattern parsing code Date: Tue, 29 May 2018 10:22:03 -0400 Message-Id: <1527603725-30560-24-git-send-email-jsimmons@infradead.org> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1527603725-30560-1-git-send-email-jsimmons@infradead.org> References: <1527603725-30560-1-git-send-email-jsimmons@infradead.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- Changelog: v1) Initial patch v2) Rebased patch. No changes in code from earlier patch .../lustre/include/linux/libcfs/libcfs_cpu.h | 2 +- drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c | 146 ++++++++++++--------- 2 files changed, 87 insertions(+), 61 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h index c0aa0b3..12ed0a9 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h @@ -393,7 +393,7 @@ static inline int cfs_cpu_init(void) static inline void cfs_cpu_fini(void) { - if (cfs_cpt_tab) { + if (!IS_ERR_OR_NULL(cfs_cpt_tab)) { cfs_cpt_table_free(cfs_cpt_tab); cfs_cpt_tab = NULL; } diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c b/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c index 649f7f9..aed48de 100644 --- a/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c +++ b/drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c @@ -692,11 +692,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) { @@ -860,11 +860,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(&node_mask, GFP_NOFS)) { CERROR("Failed to allocate scratch cpumask\n"); + rc = -ENOMEM; goto failed; } @@ -879,8 +881,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)) { @@ -903,37 +907,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++; } } @@ -941,87 +959,96 @@ static struct cfs_cpt_table *cfs_cpt_table_create_pattern(char *pattern) (node && ncpt > num_online_nodes()) || (!node && ncpt > num_online_cpus())) { CERROR("Invalid pattern '%s', or too many partitions %d\n", - pattern, ncpt); - return NULL; + pattern_dup, ncpt); + rc = -EINVAL; + goto err_free_str; } cptab = cfs_cpt_table_alloc(ncpt); if (!cptab) { CERROR("Failed to allocate CPU partition table\n"); - return NULL; + rc = -ENOMEM; + goto err_free_str; } if (node < 0) { /* shortcut to create CPT from NUMA & CPU topology */ - cpt = 0; - for_each_online_node(i) { - if (cpt >= ncpt) { - CERROR("CPU changed while setting CPU partition table, %d/%d\n", - cpt, ncpt); - goto failed; - } + if (cpumask_empty(cpumask_of_node(i))) + continue; rc = cfs_cpt_set_node(cptab, cpt++, i); - if (!rc) - goto failed; + if (!rc) { + rc = -EINVAL; + goto err_free_table; + } } + kfree(pattern_dup); return cptab; } high = node ? nr_node_ids - 1 : nr_cpu_ids - 1; - for (str = strim(pattern), c = 0;; c++) { + for (str = strim(str), c = 0; /* until break */; c++) { struct cfs_range_expr *range; struct cfs_expr_list *el; - char *bracket = strchr(str, '['); int n; + bracket = strchr(str, '['); if (!bracket) { if (*str) { CERROR("Invalid pattern '%s'\n", str); - goto failed; + rc = -EINVAL; + goto err_free_table; } if (c != ncpt) { CERROR("Expect %d partitions but found %d\n", ncpt, c); - goto failed; + rc = -EINVAL; + goto err_free_table; } break; } if (sscanf(str, "%d%n", &cpt, &n) < 1) { CERROR("Invalid CPU pattern '%s'\n", str); - goto failed; + rc = -EINVAL; + goto err_free_table; } if (cpt < 0 || cpt >= ncpt) { CERROR("Invalid partition id %d, total partitions %d\n", cpt, ncpt); - goto failed; + rc = -EINVAL; + goto err_free_table; } if (cfs_cpt_weight(cptab, cpt)) { CERROR("Partition %d has already been set.\n", cpt); - goto failed; + rc = -EPERM; + goto err_free_table; } str = strim(str + n); if (str != bracket) { CERROR("Invalid pattern '%s'\n", str); - goto failed; + rc = -EINVAL; + goto err_free_table; } bracket = strchr(str, ']'); if (!bracket) { CERROR("Missing right bracket for partition %d in '%s'\n", cpt, str); - goto failed; + rc = -EINVAL; + goto err_free_table; } - if (cfs_expr_list_parse(str, (bracket - str) + 1, - 0, high, &el)) { + rc = cfs_expr_list_parse(str, (bracket - str) + 1, 0, high, + &el); + if (rc) { CERROR("Can't parse number range in '%s'\n", str); - goto failed; + rc = -ERANGE; + goto err_free_table; } list_for_each_entry(range, &el->el_exprs, re_link) { @@ -1033,7 +1060,8 @@ static struct cfs_cpt_table *cfs_cpt_table_create_pattern(char *pattern) cfs_cpt_set_cpu(cptab, cpt, i); if (!rc) { cfs_expr_list_free(el); - goto failed; + rc = -EINVAL; + goto err_free_table; } } } @@ -1042,17 +1070,21 @@ static struct cfs_cpt_table *cfs_cpt_table_create_pattern(char *pattern) if (!cfs_cpt_online(cptab, cpt)) { CERROR("No online CPU is found on partition %d\n", cpt); - goto failed; + rc = -ENODEV; + goto err_free_table; } str = strim(bracket + 1); } + kfree(pattern_dup); return cptab; -failed: +err_free_table: cfs_cpt_table_free(cptab); - return NULL; +err_free_str: + kfree(pattern_dup); + return ERR_PTR(rc); } #ifdef CONFIG_HOTPLUG_CPU @@ -1079,7 +1111,7 @@ static int cfs_cpu_dead(unsigned int cpu) void cfs_cpu_fini(void) { - if (cfs_cpt_tab) + if (!IS_ERR_OR_NULL(cfs_cpt_tab)) cfs_cpt_table_free(cfs_cpt_tab); #ifdef CONFIG_HOTPLUG_CPU @@ -1112,26 +1144,20 @@ int cfs_cpu_init(void) #endif get_online_cpus(); if (*cpu_pattern) { - char *cpu_pattern_dup = kstrdup(cpu_pattern, GFP_KERNEL); - - if (!cpu_pattern_dup) { - CERROR("Failed to duplicate cpu_pattern\n"); - goto failed_alloc_table; - } - - cfs_cpt_tab = cfs_cpt_table_create_pattern(cpu_pattern_dup); - kfree(cpu_pattern_dup); - if (!cfs_cpt_tab) { - CERROR("Failed to create cptab from pattern %s\n", + cfs_cpt_tab = cfs_cpt_table_create_pattern(cpu_pattern); + if (IS_ERR(cfs_cpt_tab)) { + CERROR("Failed to create cptab from pattern '%s'\n", cpu_pattern); + ret = PTR_ERR(cfs_cpt_tab); goto failed_alloc_table; } } else { cfs_cpt_tab = cfs_cpt_table_create(cpu_npartitions); - if (!cfs_cpt_tab) { - CERROR("Failed to create ptable with npartitions %d\n", + if (IS_ERR(cfs_cpt_tab)) { + CERROR("Failed to create cptab with npartitions %d\n", cpu_npartitions); + ret = PTR_ERR(cfs_cpt_tab); goto failed_alloc_table; } } @@ -1146,7 +1172,7 @@ int cfs_cpu_init(void) failed_alloc_table: put_online_cpus(); - if (cfs_cpt_tab) + if (!IS_ERR_OR_NULL(cfs_cpt_tab)) cfs_cpt_table_free(cfs_cpt_tab); ret = -EINVAL; -- 1.8.3.1