Skip to content

Commit 08f41ca

Browse files
Zhen LeiKernel Patches Daemon
Zhen Lei
authored and
Kernel Patches Daemon
committed
livepatch: Improve the search performance of module_kallsyms_on_each_symbol()
Currently we traverse all symbols of all modules to find the specified function for the specified module. But in reality, we just need to find the given module and then traverse all the symbols in it. Let's add a new parameter 'const char *modname' to function module_kallsyms_on_each_symbol(), then we can compare the module names directly in this function and call hook 'fn' after matching. If 'modname' is NULL, the symbols of all modules are still traversed for compatibility with other usage cases. Phase1: mod1-->mod2..(subsequent modules do not need to be compared) | Phase2: -->f1-->f2-->f3 Assuming that there are m modules, each module has n symbols on average, then the time complexity is reduced from O(m * n) to O(m) + O(n). Reviewed-by: Petr Mladek <[email protected]> Signed-off-by: Zhen Lei <[email protected]> Signed-off-by: Jiri Olsa <[email protected]> Acked-by: Song Liu <[email protected]>
1 parent f7fb8b2 commit 08f41ca

File tree

5 files changed

+19
-14
lines changed

5 files changed

+19
-14
lines changed

include/linux/module.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -879,11 +879,13 @@ static inline bool module_sig_ok(struct module *module)
879879
#endif /* CONFIG_MODULE_SIG */
880880

881881
#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS)
882-
int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
882+
int module_kallsyms_on_each_symbol(const char *modname,
883+
int (*fn)(void *, const char *,
883884
struct module *, unsigned long),
884885
void *data);
885886
#else
886-
static inline int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
887+
static inline int module_kallsyms_on_each_symbol(const char *modname,
888+
int (*fn)(void *, const char *,
887889
struct module *, unsigned long),
888890
void *data)
889891
{

kernel/livepatch/core.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ static struct klp_object *klp_find_object(struct klp_patch *patch,
118118
}
119119

120120
struct klp_find_arg {
121-
const char *objname;
122121
const char *name;
123122
unsigned long addr;
124123
unsigned long count;
@@ -148,31 +147,24 @@ static int klp_find_callback(void *data, const char *name,
148147
{
149148
struct klp_find_arg *args = data;
150149

151-
if ((mod && !args->objname) || (!mod && args->objname))
152-
return 0;
153-
154150
if (strcmp(args->name, name))
155151
return 0;
156152

157-
if (args->objname && strcmp(args->objname, mod->name))
158-
return 0;
159-
160153
return klp_match_callback(data, addr);
161154
}
162155

163156
static int klp_find_object_symbol(const char *objname, const char *name,
164157
unsigned long sympos, unsigned long *addr)
165158
{
166159
struct klp_find_arg args = {
167-
.objname = objname,
168160
.name = name,
169161
.addr = 0,
170162
.count = 0,
171163
.pos = sympos,
172164
};
173165

174166
if (objname)
175-
module_kallsyms_on_each_symbol(klp_find_callback, &args);
167+
module_kallsyms_on_each_symbol(objname, klp_find_callback, &args);
176168
else
177169
kallsyms_on_each_match_symbol(klp_match_callback, name, &args);
178170

kernel/module/kallsyms.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,8 @@ unsigned long module_kallsyms_lookup_name(const char *name)
494494
return ret;
495495
}
496496

497-
int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
497+
int module_kallsyms_on_each_symbol(const char *modname,
498+
int (*fn)(void *, const char *,
498499
struct module *, unsigned long),
499500
void *data)
500501
{
@@ -509,6 +510,9 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
509510
if (mod->state == MODULE_STATE_UNFORMED)
510511
continue;
511512

513+
if (modname && strcmp(modname, mod->name))
514+
continue;
515+
512516
/* Use rcu_dereference_sched() to remain compliant with the sparse tool */
513517
preempt_disable();
514518
kallsyms = rcu_dereference_sched(mod->kallsyms);
@@ -525,6 +529,13 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
525529
if (ret != 0)
526530
goto out;
527531
}
532+
533+
/*
534+
* The given module is found, the subsequent modules do not
535+
* need to be compared.
536+
*/
537+
if (modname)
538+
break;
528539
}
529540
out:
530541
mutex_unlock(&module_mutex);

kernel/trace/bpf_trace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2735,7 +2735,7 @@ static int get_modules_for_addrs(struct module ***mods, unsigned long *addrs, u3
27352735
int err;
27362736

27372737
/* We return either err < 0 in case of error, ... */
2738-
err = module_kallsyms_on_each_symbol(module_callback, &args);
2738+
err = module_kallsyms_on_each_symbol(NULL, module_callback, &args);
27392739
if (err) {
27402740
kprobe_multi_put_modules(args.mods, args.mods_cnt);
27412741
kfree(args.mods);

kernel/trace/ftrace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8324,7 +8324,7 @@ int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *a
83248324
found_all = kallsyms_on_each_symbol(kallsyms_callback, &args);
83258325
if (found_all)
83268326
return 0;
8327-
found_all = module_kallsyms_on_each_symbol(kallsyms_callback, &args);
8327+
found_all = module_kallsyms_on_each_symbol(NULL, kallsyms_callback, &args);
83288328
return found_all ? 0 : -ESRCH;
83298329
}
83308330

0 commit comments

Comments
 (0)