155 lines
4.2 KiB
Diff
155 lines
4.2 KiB
Diff
|
|
From c2d1429ba289e9cea76dd08e24e2d40af3ab0435 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Yunfeng Ye <yeyunfeng@huawei.com>
|
||
|
|
Date: Thu, 31 Oct 2019 00:39:11 +0800
|
||
|
|
Subject: [PATCH 36/53] irqbalance: prevent NULL pointer dereference in
|
||
|
|
do_one_cpu()
|
||
|
|
|
||
|
|
add_cpu_to_cache_domain() will return NULL if memory allocation failure,
|
||
|
|
so check the return value before invoking add_cache_domain_to_package(),
|
||
|
|
and add a global variable need_rebuild to check this situation, if
|
||
|
|
need_rebuild is set, then invoke free_object_tree() and try again a few
|
||
|
|
times, if it still fail, then return scan().
|
||
|
|
|
||
|
|
In addition, also set need_rebuild where calloc fails throughout the
|
||
|
|
build_object_tree process.
|
||
|
|
|
||
|
|
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
|
||
|
|
---
|
||
|
|
cputree.c | 16 +++++++++++-----
|
||
|
|
irqbalance.c | 19 ++++++++++++++++---
|
||
|
|
irqbalance.h | 1 +
|
||
|
|
numa.c | 4 +++-
|
||
|
|
4 files changed, 31 insertions(+), 9 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/cputree.c b/cputree.c
|
||
|
|
index c1b4950..6bbc2cb 100644
|
||
|
|
--- a/cputree.c
|
||
|
|
+++ b/cputree.c
|
||
|
|
@@ -176,8 +176,10 @@ static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache,
|
||
|
|
|
||
|
|
if (!entry) {
|
||
|
|
package = calloc(1, sizeof(struct topo_obj));
|
||
|
|
- if (!package)
|
||
|
|
+ if (!package) {
|
||
|
|
+ need_rebuild = 1;
|
||
|
|
return NULL;
|
||
|
|
+ }
|
||
|
|
package->mask = package_mask;
|
||
|
|
package->obj_type = OBJ_TYPE_PACKAGE;
|
||
|
|
package->obj_type_list = &packages;
|
||
|
|
@@ -214,8 +216,10 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu,
|
||
|
|
|
||
|
|
if (!entry) {
|
||
|
|
cache = calloc(1, sizeof(struct topo_obj));
|
||
|
|
- if (!cache)
|
||
|
|
+ if (!cache) {
|
||
|
|
+ need_rebuild = 1;
|
||
|
|
return NULL;
|
||
|
|
+ }
|
||
|
|
cache->obj_type = OBJ_TYPE_CACHE;
|
||
|
|
cache->mask = cache_mask;
|
||
|
|
cache->number = cache_domain_count;
|
||
|
|
@@ -271,8 +275,10 @@ static void do_one_cpu(char *path)
|
||
|
|
return;
|
||
|
|
|
||
|
|
cpu = calloc(1, sizeof(struct topo_obj));
|
||
|
|
- if (!cpu)
|
||
|
|
+ if (!cpu) {
|
||
|
|
+ need_rebuild = 1;
|
||
|
|
return;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
cpu->obj_type = OBJ_TYPE_CPU;
|
||
|
|
|
||
|
|
@@ -372,8 +378,8 @@ static void do_one_cpu(char *path)
|
||
|
|
cpus_and(package_mask, package_mask, unbanned_cpus);
|
||
|
|
|
||
|
|
cache = add_cpu_to_cache_domain(cpu, cache_mask, nodeid);
|
||
|
|
- add_cache_domain_to_package(cache, packageid, package_mask,
|
||
|
|
- nodeid);
|
||
|
|
+ if (cache)
|
||
|
|
+ add_cache_domain_to_package(cache, packageid, package_mask, nodeid);
|
||
|
|
|
||
|
|
cpu->obj_type_list = &cpus;
|
||
|
|
cpus = g_list_append(cpus, cpu);
|
||
|
|
diff --git a/irqbalance.c b/irqbalance.c
|
||
|
|
index 3ff5f13..619f51f 100644
|
||
|
|
--- a/irqbalance.c
|
||
|
|
+++ b/irqbalance.c
|
||
|
|
@@ -52,6 +52,7 @@ int foreground_mode;
|
||
|
|
int numa_avail;
|
||
|
|
int journal_logging = 0;
|
||
|
|
int need_rescan;
|
||
|
|
+int need_rebuild;
|
||
|
|
unsigned int log_mask = TO_ALL;
|
||
|
|
const char *log_indent;
|
||
|
|
unsigned long power_thresh = ULONG_MAX;
|
||
|
|
@@ -260,14 +261,25 @@ gboolean scan(gpointer data __attribute__((unused)))
|
||
|
|
|
||
|
|
|
||
|
|
/* cope with cpu hotplug -- detected during /proc/interrupts parsing */
|
||
|
|
- if (need_rescan) {
|
||
|
|
+ if (need_rescan || need_rebuild) {
|
||
|
|
+ int try_times = 0;
|
||
|
|
+
|
||
|
|
need_rescan = 0;
|
||
|
|
cycle_count = 0;
|
||
|
|
log(TO_CONSOLE, LOG_INFO, "Rescanning cpu topology \n");
|
||
|
|
clear_work_stats();
|
||
|
|
|
||
|
|
- free_object_tree();
|
||
|
|
- build_object_tree();
|
||
|
|
+ do {
|
||
|
|
+ free_object_tree();
|
||
|
|
+ if (++try_times > 3) {
|
||
|
|
+ log(TO_CONSOLE, LOG_WARNING, "Rescanning cpu topology: fail\n");
|
||
|
|
+ goto out;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ need_rebuild = 0;
|
||
|
|
+ build_object_tree();
|
||
|
|
+ } while (need_rebuild);
|
||
|
|
+
|
||
|
|
for_each_irq(NULL, force_rebalance_irq, NULL);
|
||
|
|
parse_proc_interrupts();
|
||
|
|
parse_proc_stat();
|
||
|
|
@@ -284,6 +296,7 @@ gboolean scan(gpointer data __attribute__((unused)))
|
||
|
|
calculate_placement();
|
||
|
|
activate_mappings();
|
||
|
|
|
||
|
|
+out:
|
||
|
|
if (debug_mode)
|
||
|
|
dump_tree();
|
||
|
|
if (one_shot_mode)
|
||
|
|
diff --git a/irqbalance.h b/irqbalance.h
|
||
|
|
index 62c7151..79f5450 100644
|
||
|
|
--- a/irqbalance.h
|
||
|
|
+++ b/irqbalance.h
|
||
|
|
@@ -67,6 +67,7 @@ extern int debug_mode;
|
||
|
|
extern int journal_logging;
|
||
|
|
extern int one_shot_mode;
|
||
|
|
extern int need_rescan;
|
||
|
|
+extern int need_rebuild;
|
||
|
|
extern unsigned long long cycle_count;
|
||
|
|
extern unsigned long power_thresh;
|
||
|
|
extern unsigned long deepest_cache;
|
||
|
|
diff --git a/numa.c b/numa.c
|
||
|
|
index e76b6e0..9d55784 100644
|
||
|
|
--- a/numa.c
|
||
|
|
+++ b/numa.c
|
||
|
|
@@ -58,8 +58,10 @@ static void add_one_node(const char *nodename)
|
||
|
|
struct topo_obj *new;
|
||
|
|
|
||
|
|
new = calloc(1, sizeof(struct topo_obj));
|
||
|
|
- if (!new)
|
||
|
|
+ if (!new) {
|
||
|
|
+ need_rebuild = 1;
|
||
|
|
return;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
cpus_clear(new->mask);
|
||
|
|
sprintf(path, "%s/%s/cpumap", SYSFS_NODE_PATH, nodename);
|
||
|
|
--
|
||
|
|
2.23.0
|
||
|
|
|