diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-11-08 12:52:21 -0500 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2013-11-20 10:30:57 -0500 |
commit | 3247343118daa73f2b94b7fa565425d1d9f9ac84 (patch) | |
tree | db1b65941295431fbbb5cc8d822c0ebe0e0b6757 /kernel/events | |
parent | caea6cf52139116e43e615d87fcbf9823e197fdf (diff) |
uprobes: Add uprobe_task->dup_xol_work/dup_xol_addr
uprobe_task->vaddr is a bit strange. The generic code uses it only
to pass the additional argument to arch_uprobe_pre_xol(), and since
it is always equal to instruction_pointer() this looks even more
strange.
And both utask->vaddr and and utask->autask have the same scope,
they only have the meaning when the task executes the probed insn
out-of-line, so it is safe to reuse both in UTASK_RUNNING state.
This all means that logically ->vaddr belongs to arch_uprobe_task
and we should probably move it there, arch_uprobe_pre_xol() can
record instruction_pointer() itself.
OTOH, it is also used by uprobe_copy_process() and dup_xol_work()
for another purpose, this doesn't look clean and doesn't allow to
move this member into arch_uprobe_task.
This patch adds the union with 2 anonymous structs into uprobe_task.
The first struct is autask + vaddr, this way we "almost" move vaddr
into autask.
The second struct has 2 new members for uprobe_copy_process() paths:
->dup_xol_addr which can be used instead ->vaddr, and ->dup_xol_work
which can be used to avoid kmalloc() and simplify the code.
Note that this union will likely have another member(s), we need
something like "private_data_for_handlers" so that the tracing
handlers could use it to communicate with call_fetch() methods.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/uprobes.c | 16 |
1 files changed, 4 insertions, 12 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 24b7d6ca871b..df4ef0971266 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1403,12 +1403,10 @@ static void uprobe_warn(struct task_struct *t, const char *msg) | |||
1403 | 1403 | ||
1404 | static void dup_xol_work(struct callback_head *work) | 1404 | static void dup_xol_work(struct callback_head *work) |
1405 | { | 1405 | { |
1406 | kfree(work); | ||
1407 | |||
1408 | if (current->flags & PF_EXITING) | 1406 | if (current->flags & PF_EXITING) |
1409 | return; | 1407 | return; |
1410 | 1408 | ||
1411 | if (!__create_xol_area(current->utask->vaddr)) | 1409 | if (!__create_xol_area(current->utask->dup_xol_addr)) |
1412 | uprobe_warn(current, "dup xol area"); | 1410 | uprobe_warn(current, "dup xol area"); |
1413 | } | 1411 | } |
1414 | 1412 | ||
@@ -1419,7 +1417,6 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags) | |||
1419 | { | 1417 | { |
1420 | struct uprobe_task *utask = current->utask; | 1418 | struct uprobe_task *utask = current->utask; |
1421 | struct mm_struct *mm = current->mm; | 1419 | struct mm_struct *mm = current->mm; |
1422 | struct callback_head *work; | ||
1423 | struct xol_area *area; | 1420 | struct xol_area *area; |
1424 | 1421 | ||
1425 | t->utask = NULL; | 1422 | t->utask = NULL; |
@@ -1441,14 +1438,9 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags) | |||
1441 | if (mm == t->mm) | 1438 | if (mm == t->mm) |
1442 | return; | 1439 | return; |
1443 | 1440 | ||
1444 | /* TODO: move it into the union in uprobe_task */ | 1441 | t->utask->dup_xol_addr = area->vaddr; |
1445 | work = kmalloc(sizeof(*work), GFP_KERNEL); | 1442 | init_task_work(&t->utask->dup_xol_work, dup_xol_work); |
1446 | if (!work) | 1443 | task_work_add(t, &t->utask->dup_xol_work, true); |
1447 | return uprobe_warn(t, "dup xol area"); | ||
1448 | |||
1449 | t->utask->vaddr = area->vaddr; | ||
1450 | init_task_work(work, dup_xol_work); | ||
1451 | task_work_add(t, work, true); | ||
1452 | } | 1444 | } |
1453 | 1445 | ||
1454 | /* | 1446 | /* |