Skip to content

Commit 0e24220

Browse files
Hassan Naveedrostedt
authored andcommitted
tracing: Use xarray for syscall trace events
Currently, a lot of memory is wasted for architectures like MIPS when init_ftrace_syscalls() allocates the array for syscalls using kcalloc. This is because syscalls numbers start from 4000, 5000 or 6000 and array elements up to that point are unused. Fix this by using a data structure more suited to storing sparsely populated arrays. The XARRAY data structure, implemented using radix trees, is much more memory efficient for storing the syscalls in question. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Hassan Naveed <[email protected]> Reviewed-by: Paul Burton <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 89ed424 commit 0e24220

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

arch/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,14 @@ config RELR
960960
config ARCH_HAS_MEM_ENCRYPT
961961
bool
962962

963+
config HAVE_SPARSE_SYSCALL_NR
964+
bool
965+
help
966+
An architecture should select this if its syscall numbering is sparse
967+
to save space. For example, MIPS architecture has a syscall array with
968+
entries at 4000, 5000 and 6000 locations. This option turns on syscall
969+
related optimizations for a given architecture.
970+
963971
source "kernel/gcov/Kconfig"
964972

965973
source "scripts/gcc-plugins/Kconfig"

kernel/trace/trace_syscalls.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */
88
#include <linux/ftrace.h>
99
#include <linux/perf_event.h>
10+
#include <linux/xarray.h>
1011
#include <asm/syscall.h>
1112

1213
#include "trace_output.h"
@@ -30,6 +31,7 @@ syscall_get_enter_fields(struct trace_event_call *call)
3031
extern struct syscall_metadata *__start_syscalls_metadata[];
3132
extern struct syscall_metadata *__stop_syscalls_metadata[];
3233

34+
static DEFINE_XARRAY(syscalls_metadata_sparse);
3335
static struct syscall_metadata **syscalls_metadata;
3436

3537
#ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME
@@ -101,6 +103,9 @@ find_syscall_meta(unsigned long syscall)
101103

102104
static struct syscall_metadata *syscall_nr_to_meta(int nr)
103105
{
106+
if (IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR))
107+
return xa_load(&syscalls_metadata_sparse, (unsigned long)nr);
108+
104109
if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
105110
return NULL;
106111

@@ -536,12 +541,16 @@ void __init init_ftrace_syscalls(void)
536541
struct syscall_metadata *meta;
537542
unsigned long addr;
538543
int i;
539-
540-
syscalls_metadata = kcalloc(NR_syscalls, sizeof(*syscalls_metadata),
541-
GFP_KERNEL);
542-
if (!syscalls_metadata) {
543-
WARN_ON(1);
544-
return;
544+
void *ret;
545+
546+
if (!IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR)) {
547+
syscalls_metadata = kcalloc(NR_syscalls,
548+
sizeof(*syscalls_metadata),
549+
GFP_KERNEL);
550+
if (!syscalls_metadata) {
551+
WARN_ON(1);
552+
return;
553+
}
545554
}
546555

547556
for (i = 0; i < NR_syscalls; i++) {
@@ -551,7 +560,16 @@ void __init init_ftrace_syscalls(void)
551560
continue;
552561

553562
meta->syscall_nr = i;
554-
syscalls_metadata[i] = meta;
563+
564+
if (!IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR)) {
565+
syscalls_metadata[i] = meta;
566+
} else {
567+
ret = xa_store(&syscalls_metadata_sparse, i, meta,
568+
GFP_KERNEL);
569+
WARN(xa_is_err(ret),
570+
"Syscall memory allocation failed\n");
571+
}
572+
555573
}
556574
}
557575

0 commit comments

Comments
 (0)