e1f6e2b6fb
Release: crash-7.3.0-5 Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
152 lines
4.1 KiB
Diff
152 lines
4.1 KiB
Diff
From 2fab8fbc0c4f1c4cbe889de4cead5f7457a19f77 Mon Sep 17 00:00:00 2001
|
|
From: Tao Liu <ltao@redhat.com>
|
|
Date: Sat, 16 Oct 2021 13:21:11 +0800
|
|
Subject: [PATCH 1/9] symbols: Implement install and remove operations for
|
|
mod_symname_hash
|
|
|
|
Currently the sequence for symbol_search to search a symbol is: 1) kernel
|
|
symname hash table, 2) iterate all kernel symbols, 3) iterate all kernel
|
|
modules and their symbols. In the worst case, if a non-exist symbol been
|
|
searched, all 3 stages will be went through. The time consuming status for
|
|
each stage is like:
|
|
|
|
stage 1 stage 2 stage 3
|
|
0.007000(ms) 0.593000(ms) 2.421000(ms)
|
|
|
|
stage 3 takes too much time when comparing to stage 1. This patch series
|
|
introduces a symname hash table for kernel modules, to improve the
|
|
performance of symbol searching.
|
|
|
|
Functions symbol_search() and symbol_exists() are fundamental and widely
|
|
used by other crash functions, thus the benefit of performance improvement
|
|
can get accumulated. For example, "ps -m" and "irq" commands, which call
|
|
the functions many times, will become faster with the patch series.
|
|
|
|
This patch indroduces mod_symname_hash, and its install/remove operations.
|
|
Since symbol_search() has to return the lowest address symbol and
|
|
symbol_search_next() returns the next lowest symbol, thus the installation
|
|
should be sorted ascendingly.
|
|
|
|
In mod_symname_hash_install_range() scenario, spn are already arranged
|
|
ascendingly, so for mod_symname_hash_install():
|
|
|
|
Install spn previous to sp:
|
|
|
|
If sp is the start of bucket, or
|
|
1) spn->value is smaller than sp->value.
|
|
|
|
Install spn next to sp:
|
|
|
|
1) sp->name_hash_next is NULL, or
|
|
2) sp->name_hash_next->value is larger than spn->value
|
|
|
|
spn->value is the kernel address of the symbol and will not change.
|
|
So we use it mainly to determine the sequence. When spn->value equals
|
|
sp->value, they must be symbols within a kernel module.
|
|
|
|
Signed-off-by: Tao Liu <ltao@redhat.com>
|
|
---
|
|
defs.h | 1 +
|
|
symbols.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 74 insertions(+)
|
|
|
|
diff --git a/defs.h b/defs.h
|
|
index cbd45e52f9da..bbdca799f72d 100644
|
|
--- a/defs.h
|
|
+++ b/defs.h
|
|
@@ -2755,6 +2755,7 @@ struct symbol_table_data {
|
|
double val_hash_searches;
|
|
double val_hash_iterations;
|
|
struct syment *symname_hash[SYMNAME_HASH];
|
|
+ struct syment *mod_symname_hash[SYMNAME_HASH];
|
|
struct symbol_namespace kernel_namespace;
|
|
struct syment *ext_module_symtable;
|
|
struct syment *ext_module_symend;
|
|
diff --git a/symbols.c b/symbols.c
|
|
index 69dccdb09d5f..ad12d1c22225 100644
|
|
--- a/symbols.c
|
|
+++ b/symbols.c
|
|
@@ -1157,6 +1157,79 @@ symname_hash_install(struct syment *spn)
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+ * Install a single kernel module symbol into the mod_symname_hash.
|
|
+ */
|
|
+static void
|
|
+mod_symname_hash_install(struct syment *spn)
|
|
+{
|
|
+ struct syment *sp;
|
|
+ int index;
|
|
+
|
|
+ if (!spn)
|
|
+ return;
|
|
+
|
|
+ index = SYMNAME_HASH_INDEX(spn->name);
|
|
+
|
|
+ sp = st->mod_symname_hash[index];
|
|
+
|
|
+ if (!sp || (spn->value < sp->value)) {
|
|
+ st->mod_symname_hash[index] = spn;
|
|
+ spn->name_hash_next = sp;
|
|
+ return;
|
|
+ }
|
|
+ for (; sp; sp = sp->name_hash_next) {
|
|
+ if (!sp->name_hash_next ||
|
|
+ spn->value < sp->name_hash_next->value) {
|
|
+ spn->name_hash_next = sp->name_hash_next;
|
|
+ sp->name_hash_next = spn;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+mod_symname_hash_remove(struct syment *spn)
|
|
+{
|
|
+ struct syment *sp;
|
|
+ int index;
|
|
+
|
|
+ if (!spn)
|
|
+ return;
|
|
+
|
|
+ index = SYMNAME_HASH_INDEX(spn->name);
|
|
+
|
|
+ if (st->mod_symname_hash[index] == spn) {
|
|
+ st->mod_symname_hash[index] = spn->name_hash_next;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (sp = st->mod_symname_hash[index]; sp; sp = sp->name_hash_next) {
|
|
+ if (sp->name_hash_next == spn) {
|
|
+ sp->name_hash_next = spn->name_hash_next;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+mod_symtable_hash_install_range(struct syment *from, struct syment *to)
|
|
+{
|
|
+ struct syment *sp;
|
|
+
|
|
+ for (sp = from; sp <= to; sp++)
|
|
+ mod_symname_hash_install(sp);
|
|
+}
|
|
+
|
|
+static void
|
|
+mod_symtable_hash_remove_range(struct syment *from, struct syment *to)
|
|
+{
|
|
+ struct syment *sp;
|
|
+
|
|
+ for (sp = from; sp <= to; sp++)
|
|
+ mod_symname_hash_remove(sp);
|
|
+}
|
|
+
|
|
/*
|
|
* Static kernel symbol value search
|
|
*/
|
|
--
|
|
2.30.2
|
|
|