Systemtap - вызов системного вызова из пространства ядра
Я пытаюсь создать жесткую ссылку, вызывая sys_link напрямую из кода Systemtap Embedded C. По сути, код выглядит так:
function sys_link:long(oldname, newname) %{ /* pure */
int error;
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(get_ds());
error = psys_link(STAP_ARG_oldname, STAP_ARG_newname);
set_fs(old_fs);
STAP_RETURN(error);
%}
sys_link не экспортируется ядром, поэтому psys_link разрешается с помощью kallsyms_lookup_name() при инициализации, и я могу проверить, что адрес разрешен правильно. Кажется, системный вызов вызывается, но он никогда не возвращается.
* Я ЗНАЮ, что это не лучшая идея вызывать системные вызовы из пространства ядра, но поверьте мне, мне нужно сделать это;) *
С другой стороны, я провел еще один более простой тест, вызвав filp_open, который экспортируется ядром, и это даже не системный вызов, а просто функция ядра, чтобы создать файл с такими же неудачными результатами:
function myopen:long(newname) %{ /* pure */
struct file *file;
mm_segment_t old_fs = get_fs();
set_fs(get_ds());
file = filp_open(STAP_ARG_newname, O_WRONLY|O_CREAT, 0644);
set_fs(old_fs);
STAP_RETURN(1);
%}
Любая подсказка, почему ядро замерзает?
ОБНОВЛЕНИЕ: системный вызов и функция вызываются в контексте проверки syscall.open.return. Как обсуждалось в одном из комментариев, зонды возврата Systemtap реализованы с использованием kretprobe... который заменяет адрес возврата функции для батута... что AFAIU означает, что процедура syscall уже завершена, и это должно было снять любую блокировку, связанную с сама файловая система, но я, вероятно, что-то упустил.
Отладка ядра в этот момент дает мне следующую трассировку. По-видимому, тупик находится в блокировке kprobe.
>>> info threads
Id Target Id Frame
* 1 Thread 1 (CPU#0 [running]) __loop_delay () at arch/arm/lib/delay-loop.S:42
2 Thread 2 (CPU#1 [running]) __loop_delay () at arch/arm/lib/delay-loop.S:42
3 Thread 3 (CPU#2 [running]) __loop_delay () at arch/arm/lib/delay-loop.S:42
4 Thread 4 (CPU#3 [running]) arch_spin_lock (lock=<optimised out>) at ./arch/arm/include/asm/spinlock.h:91
>>> thread 4
[Switching to thread 4 (Thread 4)]
#0 arch_spin_lock (lock=<optimised out>) at ./arch/arm/include/asm/spinlock.h:91
91 wfe();
>>> bt
#0 arch_spin_lock (lock=<optimised out>) at ./arch/arm/include/asm/spinlock.h:91
#1 do_raw_spin_lock_flags (flags=<optimised out>, lock=<optimised out>) at ./include/linux/spinlock.h:155
#2 __raw_spin_lock_irqsave (lock=<optimised out>) at ./include/linux/spinlock_api_smp.h:121
#3 _raw_spin_lock_irqsave (lock=0xc1541f80 <kretprobe_table_locks+2240>) at kernel/locking/spinlock.c:159
#4 0xc0412d18 in kretprobe_table_lock (flags=<optimised out>, hash=<optimised out>) at kernel/kprobes.c:1113
#5 kprobe_flush_task (tk=0xed165b00) at kernel/kprobes.c:1158
#6 0xc03814f8 in finish_task_switch (prev=0xed165b00) at kernel/sched/core.c:2783
#7 0xc0c19c38 in context_switch (cookie=..., next=<optimised out>, prev=<optimised out>, rq=<optimised out>) at kernel/sched/core.c:2902
#8 __schedule (preempt=<optimised out>) at kernel/sched/core.c:3402
#9 0xc0c1a1a4 in schedule () at kernel/sched/core.c:3457
#10 0xc0c1a54c in schedule_preempt_disabled () at kernel/sched/core.c:3490
#11 0xc03a23dc in cpu_idle_loop () at kernel/sched/idle.c:273
#12 cpu_startup_entry (state=<optimised out>) at kernel/sched/idle.c:302
#13 0xc031206c in secondary_start_kernel () at arch/arm/kernel/smp.c:412
#14 0x60301dec in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
ПРИМЕЧАНИЕ. Это трассировка ARM-машины, но тот же результат происходит в i386.
1 ответ
Обработчики тестов Systemtap, как правило, запускаются из атомарного контекста, что означает, что прерывание и / или прерывания отключены. Если вам удастся вызвать функцию ядра из такого контекста, целевая функция должна быть аналогично "атомарной", то есть никогда не брать новые блокировки или блоки.