* [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id
@ 2012-05-29 19:27 Oleg Nesterov
2012-05-29 19:27 ` [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm Oleg Nesterov
` (7 more replies)
0 siblings, 8 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:27 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
Hello,
Basically the same changes we discussed before.
Changes:
- do not introduce is_swbp_at_addr_fast(), change
is_swbp_at_addr() to check current->mm == mm as
Peter suggested
- 2/7 is new
Oleg.
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
@ 2012-05-29 19:27 ` Oleg Nesterov
2012-06-06 15:08 ` [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-%3Emm tip-bot for Oleg Nesterov
2012-06-06 16:05 ` [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-> mm tip-bot for Oleg Nesterov
2012-05-29 19:27 ` [PATCH 2/7] uprobes: change read_opcode() to use FOLL_FORCE Oleg Nesterov
` (6 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:27 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
Change is_swbp_at_addr() to try to avoid the costly read_opcode()
if mm == current->mm, __copy_from_user_inatomic() should succeed
in the likely case.
Currently this optimization is not important, but we are going to
add more is_swbp_at_addr(current->mm) callers.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/events/uprobes.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 985be4d..d0f5ec0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -333,10 +333,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
uprobe_opcode_t opcode;
int result;
+ if (current->mm == mm) {
+ pagefault_disable();
+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+ sizeof(opcode));
+ pagefault_enable();
+
+ if (likely(result == 0))
+ goto out;
+ }
+
result = read_opcode(mm, vaddr, &opcode);
if (result)
return result;
-
+out:
if (is_swbp_insn(&opcode))
return 1;
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 2/7] uprobes: change read_opcode() to use FOLL_FORCE
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-29 19:27 ` [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm Oleg Nesterov
@ 2012-05-29 19:27 ` Oleg Nesterov
2012-06-06 15:09 ` [tip:perf/core] uprobes: Change " tip-bot for Oleg Nesterov
2012-06-06 16:06 ` tip-bot for Oleg Nesterov
2012-05-29 19:28 ` [PATCH 3/7] uprobes: introduce find_active_uprobe() helper Oleg Nesterov
` (5 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:27 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
set_orig_insn()->read_opcode() should not fail if the probed task
did mprotect() after uprobe_register(), change it to use FOLL_FORCE.
Without FOLL_WRITE this doesn't have any "side" effect but allows
to read the !VM_READ memory.
There is another reason for this change, we are going to use
is_swbp_at_addr() from handle_swbp() which can race with another
thread doing mprotect().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/events/uprobes.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d0f5ec0..a0dbc87 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -312,7 +312,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_
void *vaddr_new;
int ret;
- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
if (ret <= 0)
return ret;
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 3/7] uprobes: introduce find_active_uprobe() helper
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-29 19:27 ` [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm Oleg Nesterov
2012-05-29 19:27 ` [PATCH 2/7] uprobes: change read_opcode() to use FOLL_FORCE Oleg Nesterov
@ 2012-05-29 19:28 ` Oleg Nesterov
2012-06-06 15:10 ` [tip:perf/core] uprobes: Introduce " tip-bot for Oleg Nesterov
2012-06-06 16:07 ` tip-bot for Oleg Nesterov
2012-05-29 19:29 ` [PATCH 4/7] uprobes: teach find_active_uprobe() to provide the "is_swbp" info Oleg Nesterov
` (4 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:28 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
No functional changes. Move the "find uprobe" code from
handle_swbp() to the new helper, find_active_uprobe().
Note: with or without this change, the find-active-uprobe logic
is not exactly right. We can race with another thread which unmaps
the memory with the valid uprobe before we take mm->mmap_sem. We
can't find this uprobe simply because find_vma() fails. In this
case we wrongly assume that this trap was not caused by uprobe
and send the erroneous SIGTRAP. See the next changes.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/events/uprobes.c | 47 ++++++++++++++++++++++++++++-------------------
1 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a0dbc87..eaf4d55 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1489,38 +1489,47 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
return false;
}
-/*
- * Run handler and ask thread to singlestep.
- * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
- */
-static void handle_swbp(struct pt_regs *regs)
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
{
+ struct mm_struct *mm = current->mm;
+ struct uprobe *uprobe = NULL;
struct vm_area_struct *vma;
- struct uprobe_task *utask;
- struct uprobe *uprobe;
- struct mm_struct *mm;
- unsigned long bp_vaddr;
- uprobe = NULL;
- bp_vaddr = uprobe_get_swbp_addr(regs);
- mm = current->mm;
down_read(&mm->mmap_sem);
vma = find_vma(mm, bp_vaddr);
- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
- struct inode *inode;
- loff_t offset;
+ if (vma && vma->vm_start <= bp_vaddr) {
+ if (valid_vma(vma, false)) {
+ struct inode *inode;
+ loff_t offset;
- inode = vma->vm_file->f_mapping->host;
- offset = bp_vaddr - vma->vm_start;
- offset += (vma->vm_pgoff << PAGE_SHIFT);
- uprobe = find_uprobe(inode, offset);
+ inode = vma->vm_file->f_mapping->host;
+ offset = bp_vaddr - vma->vm_start;
+ offset += (vma->vm_pgoff << PAGE_SHIFT);
+ uprobe = find_uprobe(inode, offset);
+ }
}
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
current->uprobe_srcu_id = -1;
up_read(&mm->mmap_sem);
+ return uprobe;
+}
+
+/*
+ * Run handler and ask thread to singlestep.
+ * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
+ */
+static void handle_swbp(struct pt_regs *regs)
+{
+ struct uprobe_task *utask;
+ struct uprobe *uprobe;
+ unsigned long bp_vaddr;
+
+ bp_vaddr = uprobe_get_swbp_addr(regs);
+ uprobe = find_active_uprobe(bp_vaddr);
+
if (!uprobe) {
/* No matching uprobe; signal SIGTRAP. */
send_sig(SIGTRAP, current, 0);
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 4/7] uprobes: teach find_active_uprobe() to provide the "is_swbp" info
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
` (2 preceding siblings ...)
2012-05-29 19:28 ` [PATCH 3/7] uprobes: introduce find_active_uprobe() helper Oleg Nesterov
@ 2012-05-29 19:29 ` Oleg Nesterov
2012-06-06 15:10 ` [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the %22is_swbp%22 info tip-bot for Oleg Nesterov
2012-06-06 16:08 ` [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the "is_swbp" info tip-bot for Oleg Nesterov
2012-05-29 19:29 ` [PATCH 5/7] uprobes: change register_for_each_vma() to take mm->mmap_sem for writing Oleg Nesterov
` (3 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:29 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
A separate patch to simplify the review, and for the documentation.
The patch adds another "int *is_swbp" argument to find_active_uprobe(),
so far its only caller doesn't use this info.
With this patch find_active_uprobe() additionally does:
- if find_vma() + ->vm_start check fails, *is_swbp = -EFAULT
- otherwise, if valid_vma() + find_uprobe() fails, it holds
the result of is_swbp_at_addr(), can be negative too. The
latter is only possible if we raced with another thread
which did munmap/etc after we hit this bp.
IOW. If find_active_uprobe(&is_swbp) returns NULL, the caller can
look at is_swbp to figure out whether the current insn is bp or not,
or detect the race with another thread if it is negative.
Note: I think that performance-wise this change is fine. This adds
is_swbp_at_addr(), but only if we raced with uprobe_unregister() or
if we hit the "normal" int3 but this mm has uprobes as well. And even
in this case the slow read_opcode() path is very unlikely, this insn
recently triggered do_int3(), __copy_from_user_inatomic() shouldn't
fail in the likely case.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/events/uprobes.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index eaf4d55..ee3df70 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1489,7 +1489,7 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
return false;
}
-static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
{
struct mm_struct *mm = current->mm;
struct uprobe *uprobe = NULL;
@@ -1497,7 +1497,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
down_read(&mm->mmap_sem);
vma = find_vma(mm, bp_vaddr);
-
if (vma && vma->vm_start <= bp_vaddr) {
if (valid_vma(vma, false)) {
struct inode *inode;
@@ -1508,6 +1507,11 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
offset += (vma->vm_pgoff << PAGE_SHIFT);
uprobe = find_uprobe(inode, offset);
}
+
+ if (!uprobe)
+ *is_swbp = is_swbp_at_addr(mm, bp_vaddr);
+ } else {
+ *is_swbp = -EFAULT;
}
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
@@ -1526,9 +1530,10 @@ static void handle_swbp(struct pt_regs *regs)
struct uprobe_task *utask;
struct uprobe *uprobe;
unsigned long bp_vaddr;
+ int is_swbp;
bp_vaddr = uprobe_get_swbp_addr(regs);
- uprobe = find_active_uprobe(bp_vaddr);
+ uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
/* No matching uprobe; signal SIGTRAP. */
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 5/7] uprobes: change register_for_each_vma() to take mm->mmap_sem for writing
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
` (3 preceding siblings ...)
2012-05-29 19:29 ` [PATCH 4/7] uprobes: teach find_active_uprobe() to provide the "is_swbp" info Oleg Nesterov
@ 2012-05-29 19:29 ` Oleg Nesterov
2012-06-06 15:11 ` [tip:perf/core] uprobes: Change register_for_each_vma() to take mm-%3Emmap_sem " tip-bot for Oleg Nesterov
2012-06-06 16:09 ` [tip:perf/core] uprobes: Change register_for_each_vma() to take mm->mmap_sem " tip-bot for Oleg Nesterov
2012-05-29 19:29 ` [PATCH 6/7] uprobes: teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu Oleg Nesterov
` (2 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:29 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
Change register_for_each_vma() to take mm->mmap_sem for writing.
This is a bit unfortunate but hopefully not too bad, this is the
slow path anyway.
This is needed to ensure that find_active_uprobe() can not race
with uprobe_register() which adds the new bp at the same bp_vaddr,
after find_uprobe() fails and before is_swbp_at_addr_fast() checks
the memory.
IOW, this is needed to ensure that if find_active_uprobe() returns
NULL but is_swbp == true, we can safely assume that it was the
"normal" int3 and we should send SIGTRAP.
There is another reason for this change. We are going to replace
uprobes_state->count with MMF_ flags set by register/unregister
and cleared by find_active_uprobe(), and set/clear shouldn't race
with each other.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/events/uprobes.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ee3df70..a2ed82b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -853,12 +853,12 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
}
mm = vi->mm;
- down_read(&mm->mmap_sem);
+ down_write(&mm->mmap_sem);
vma = find_vma(mm, (unsigned long)vi->vaddr);
if (!vma || !valid_vma(vma, is_register)) {
list_del(&vi->probe_list);
kfree(vi);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
continue;
}
@@ -867,7 +867,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
vaddr != vi->vaddr) {
list_del(&vi->probe_list);
kfree(vi);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
continue;
}
@@ -877,7 +877,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
else
remove_breakpoint(uprobe, mm, vi->vaddr);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
if (is_register) {
if (ret && ret == -EEXIST)
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 6/7] uprobes: teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
` (4 preceding siblings ...)
2012-05-29 19:29 ` [PATCH 5/7] uprobes: change register_for_each_vma() to take mm->mmap_sem for writing Oleg Nesterov
@ 2012-05-29 19:29 ` Oleg Nesterov
2012-06-06 15:12 ` [tip:perf/core] uprobes: Teach handle_swbp() to rely on %22is_swbp%22 " tip-bot for Oleg Nesterov
2012-06-06 16:10 ` [tip:perf/core] uprobes: Teach handle_swbp() to rely on "is_swbp" " tip-bot for Oleg Nesterov
2012-05-29 19:30 ` [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-31 5:40 ` [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Srikar Dronamraju
7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:29 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
Currently handle_swbp() assumes that it can't race with unregister,
so it roughly does:
if (find_uprobe(vaddr))
process_uprobe();
else
send_sig(SIGTRAP);
This relies on the not-really-working uprobes_srcu code we are going
to remove, see the next patch.
With this patch we rely on the result of is_swbp_at_addr(bp_vaddr)
if find_uprobe() fails.
If is_swbp == 1, then we hit the normal int3, we should send SIGTRAP.
If is_swbp == 0, we raced with uprobe_unregister(), we simply restart
this insn again.
The "difficult" case is is_swbp == -EFAULT, when we can't read this
memory. In this case I think we should restart too, and this is more
correct compared to the current code which sends SIGTRAP.
Ignoring ENOMEM/etc from get_user_pages(), this can only happen if
another thread unmaps this memory before find_active_uprobe() takes
mmap_sem. It would be better to pretend it was unmapped before this
insn was executed, restart, and get SIGSEGV.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/events/uprobes.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a2ed82b..1f02e3b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1530,14 +1530,26 @@ static void handle_swbp(struct pt_regs *regs)
struct uprobe_task *utask;
struct uprobe *uprobe;
unsigned long bp_vaddr;
- int is_swbp;
+ int uninitialized_var(is_swbp);
bp_vaddr = uprobe_get_swbp_addr(regs);
uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
- /* No matching uprobe; signal SIGTRAP. */
- send_sig(SIGTRAP, current, 0);
+ if (is_swbp > 0) {
+ /* No matching uprobe; signal SIGTRAP. */
+ send_sig(SIGTRAP, current, 0);
+ } else {
+ /*
+ * Either we raced with uprobe_unregister() or we can't
+ * access this memory. The latter is only possible if
+ * another thread plays with our ->mm. In both cases
+ * we can simply restart. If this vma was unmapped we
+ * can pretend this insn was not executed yet and get
+ * the (correct) SIGSEGV after restart.
+ */
+ instruction_pointer_set(regs, bp_vaddr);
+ }
return;
}
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
` (5 preceding siblings ...)
2012-05-29 19:29 ` [PATCH 6/7] uprobes: teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu Oleg Nesterov
@ 2012-05-29 19:30 ` Oleg Nesterov
2012-05-29 23:04 ` Peter Zijlstra
` (2 more replies)
2012-05-31 5:40 ` [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Srikar Dronamraju
7 siblings, 3 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-05-29 19:30 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
Cc: Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
Kill the no longer needed uprobes_srcu/uprobe_srcu_id code.
It doesn't really work anyway. synchronize_srcu() can only synchronize
with the code "inside" the srcu_read_lock/srcu_read_unlock section,
while uprobe_pre_sstep_notifier() does srcu_read_lock() _after_ we
already hit the breakpoint.
I guess this probably works "in practice". synchronize_srcu() is slow
and it implies synchronize_sched(), and the probed task enters the non-
preemptible section at the start of exception handler. Still this is not
right at least in theory, and task->uprobe_srcu_id blows task_struct.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
include/linux/sched.h | 1 -
kernel/events/uprobes.c | 22 +++-------------------
2 files changed, 3 insertions(+), 20 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f45c0b2..411827e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1574,7 +1574,6 @@ struct task_struct {
#endif
#ifdef CONFIG_UPROBES
struct uprobe_task *utask;
- int uprobe_srcu_id;
#endif
};
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1f02e3b..8c5e043 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -38,7 +38,6 @@
#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE
-static struct srcu_struct uprobes_srcu;
static struct rb_root uprobes_tree = RB_ROOT;
static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */
@@ -738,20 +737,14 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
}
/*
- * There could be threads that have hit the breakpoint and are entering the
- * notifier code and trying to acquire the uprobes_treelock. The thread
- * calling delete_uprobe() that is removing the uprobe from the rb_tree can
- * race with these threads and might acquire the uprobes_treelock compared
- * to some of the breakpoint hit threads. In such a case, the breakpoint
- * hit threads will not find the uprobe. The current unregistering thread
- * waits till all other threads have hit a breakpoint, to acquire the
- * uprobes_treelock before the uprobe is removed from the rbtree.
+ * There could be threads that have already hit the breakpoint. They
+ * will recheck the current insn and restart if find_uprobe() fails.
+ * See find_active_uprobe().
*/
static void delete_uprobe(struct uprobe *uprobe)
{
unsigned long flags;
- synchronize_srcu(&uprobes_srcu);
spin_lock_irqsave(&uprobes_treelock, flags);
rb_erase(&uprobe->rb_node, &uprobes_tree);
spin_unlock_irqrestore(&uprobes_treelock, flags);
@@ -1388,9 +1381,6 @@ void uprobe_free_utask(struct task_struct *t)
{
struct uprobe_task *utask = t->utask;
- if (t->uprobe_srcu_id != -1)
- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
-
if (!utask)
return;
@@ -1408,7 +1398,6 @@ void uprobe_free_utask(struct task_struct *t)
void uprobe_copy_process(struct task_struct *t)
{
t->utask = NULL;
- t->uprobe_srcu_id = -1;
}
/*
@@ -1513,9 +1502,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
} else {
*is_swbp = -EFAULT;
}
-
- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
- current->uprobe_srcu_id = -1;
up_read(&mm->mmap_sem);
return uprobe;
@@ -1656,7 +1642,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
utask->state = UTASK_BP_HIT;
set_thread_flag(TIF_UPROBE);
- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
return 1;
}
@@ -1691,7 +1676,6 @@ static int __init init_uprobes(void)
mutex_init(&uprobes_mutex[i]);
mutex_init(&uprobes_mmap_mutex[i]);
}
- init_srcu_struct(&uprobes_srcu);
return register_die_notifier(&uprobe_exception_nb);
}
--
1.5.5.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id
2012-05-29 19:30 ` [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
@ 2012-05-29 23:04 ` Peter Zijlstra
2012-05-30 1:51 ` Paul E. McKenney
2012-06-06 15:13 ` [tip:perf/core] uprobes: Kill uprobes_srcu/uprobe_srcu_id tip-bot for Oleg Nesterov
2012-06-06 16:10 ` tip-bot for Oleg Nesterov
2 siblings, 1 reply; 25+ messages in thread
From: Peter Zijlstra @ 2012-05-29 23:04 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Ingo Molnar, Srikar Dronamraju, Ananth N Mavinakayanahalli,
Anton Arapov, Linus Torvalds, Masami Hiramatsu, linux-kernel,
Paul E. McKenney
On Tue, 2012-05-29 at 21:30 +0200, Oleg Nesterov wrote:
> Kill the no longer needed uprobes_srcu/uprobe_srcu_id code.
>
> It doesn't really work anyway. synchronize_srcu() can only synchronize
> with the code "inside" the srcu_read_lock/srcu_read_unlock section,
> while uprobe_pre_sstep_notifier() does srcu_read_lock() _after_ we
> already hit the breakpoint.
>
> I guess this probably works "in practice". synchronize_srcu() is slow
> and it implies synchronize_sched(), and the probed task enters the non-
> preemptible section at the start of exception handler. Still this is not
> right at least in theory, and task->uprobe_srcu_id blows task_struct.
This kills the only user of srcu_read_{,un}lock_raw(), so I guess we
could also make:
9ceae0e2
101db7b4
0c53dd8b
go away..
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id
2012-05-29 23:04 ` Peter Zijlstra
@ 2012-05-30 1:51 ` Paul E. McKenney
0 siblings, 0 replies; 25+ messages in thread
From: Paul E. McKenney @ 2012-05-30 1:51 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Oleg Nesterov, Ingo Molnar, Srikar Dronamraju,
Ananth N Mavinakayanahalli, Anton Arapov, Linus Torvalds,
Masami Hiramatsu, linux-kernel
On Wed, May 30, 2012 at 01:04:47AM +0200, Peter Zijlstra wrote:
> On Tue, 2012-05-29 at 21:30 +0200, Oleg Nesterov wrote:
> > Kill the no longer needed uprobes_srcu/uprobe_srcu_id code.
> >
> > It doesn't really work anyway. synchronize_srcu() can only synchronize
> > with the code "inside" the srcu_read_lock/srcu_read_unlock section,
> > while uprobe_pre_sstep_notifier() does srcu_read_lock() _after_ we
> > already hit the breakpoint.
> >
> > I guess this probably works "in practice". synchronize_srcu() is slow
> > and it implies synchronize_sched(), and the probed task enters the non-
> > preemptible section at the start of exception handler. Still this is not
> > right at least in theory, and task->uprobe_srcu_id blows task_struct.
>
> This kills the only user of srcu_read_{,un}lock_raw(), so I guess we
> could also make:
>
> 9ceae0e2
> 101db7b4
> 0c53dd8b
>
> go away..
If it is still unused in a few months, I will get rid of them.
Thanx, Paul
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
` (6 preceding siblings ...)
2012-05-29 19:30 ` [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
@ 2012-05-31 5:40 ` Srikar Dronamraju
7 siblings, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2012-05-31 5:40 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
Anton Arapov, Linus Torvalds, Masami Hiramatsu, linux-kernel
> Basically the same changes we discussed before.
>
> Changes:
>
> - do not introduce is_swbp_at_addr_fast(), change
> is_swbp_at_addr() to check current->mm == mm as
> Peter suggested
>
> - 2/7 is new
>
I have reviewed and tested the patches and I am fine with all the changes.
Thanks Oleg.
--
Thanks and Regards
Srikar
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-%3Emm
2012-05-29 19:27 ` [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm Oleg Nesterov
@ 2012-06-06 15:08 ` tip-bot for Oleg Nesterov
2012-06-06 16:05 ` [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-> mm tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:08 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: a41d60e10a611f0addf2741e2d56c95e14bd5ee0
Gitweb: http://git.kernel.org/tip/a41d60e10a611f0addf2741e2d56c95e14bd5ee0
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:27:44 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:54 +0200
uprobes: Optimize is_swbp_at_addr() for current-%3Emm
Change is_swbp_at_addr() to try to avoid the costly
read_opcode() if mm == current->mm, __copy_from_user_inatomic()
should succeed in the likely case.
Currently this optimization is not important, but we are going
to add more is_swbp_at_addr(current->mm) callers.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192744.GA8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 985be4d..d0f5ec0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -333,10 +333,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
uprobe_opcode_t opcode;
int result;
+ if (current->mm == mm) {
+ pagefault_disable();
+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+ sizeof(opcode));
+ pagefault_enable();
+
+ if (likely(result == 0))
+ goto out;
+ }
+
result = read_opcode(mm, vaddr, &opcode);
if (result)
return result;
-
+out:
if (is_swbp_insn(&opcode))
return 1;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Change read_opcode() to use FOLL_FORCE
2012-05-29 19:27 ` [PATCH 2/7] uprobes: change read_opcode() to use FOLL_FORCE Oleg Nesterov
@ 2012-06-06 15:09 ` tip-bot for Oleg Nesterov
2012-06-06 16:06 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:09 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 2c357a15491100e94de8e6105e6046ee3a71e05a
Gitweb: http://git.kernel.org/tip/2c357a15491100e94de8e6105e6046ee3a71e05a
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:27:59 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:55 +0200
uprobes: Change read_opcode() to use FOLL_FORCE
set_orig_insn()->read_opcode() should not fail if the probed
task did mprotect() after uprobe_register(), change it to use
FOLL_FORCE. Without FOLL_WRITE this doesn't have any "side"
effect but allows to read the !VM_READ memory.
There is another reason for this change, we are going to use
is_swbp_at_addr() from handle_swbp() which can race with another
thread doing mprotect().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192759.GB8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d0f5ec0..a0dbc87 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -312,7 +312,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_
void *vaddr_new;
int ret;
- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
if (ret <= 0)
return ret;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Introduce find_active_uprobe() helper
2012-05-29 19:28 ` [PATCH 3/7] uprobes: introduce find_active_uprobe() helper Oleg Nesterov
@ 2012-06-06 15:10 ` tip-bot for Oleg Nesterov
2012-06-06 16:07 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:10 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 2a1bca6ff0ef8fd9b943ce2e6a8826606dc58e3f
Gitweb: http://git.kernel.org/tip/2a1bca6ff0ef8fd9b943ce2e6a8826606dc58e3f
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:28:57 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:55 +0200
uprobes: Introduce find_active_uprobe() helper
No functional changes. Move the "find uprobe" code from
handle_swbp() to the new helper, find_active_uprobe().
Note: with or without this change, the find-active-uprobe logic
is not exactly right. We can race with another thread which
unmaps the memory with the valid uprobe before we take
mm->mmap_sem. We can't find this uprobe simply because
find_vma() fails. In this case we wrongly assume that this trap
was not caused by uprobe and send the erroneous SIGTRAP. See the
next changes.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192857.GC8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 47 ++++++++++++++++++++++++++++-------------------
1 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a0dbc87..eaf4d55 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1489,38 +1489,47 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
return false;
}
-/*
- * Run handler and ask thread to singlestep.
- * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
- */
-static void handle_swbp(struct pt_regs *regs)
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
{
+ struct mm_struct *mm = current->mm;
+ struct uprobe *uprobe = NULL;
struct vm_area_struct *vma;
- struct uprobe_task *utask;
- struct uprobe *uprobe;
- struct mm_struct *mm;
- unsigned long bp_vaddr;
- uprobe = NULL;
- bp_vaddr = uprobe_get_swbp_addr(regs);
- mm = current->mm;
down_read(&mm->mmap_sem);
vma = find_vma(mm, bp_vaddr);
- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
- struct inode *inode;
- loff_t offset;
+ if (vma && vma->vm_start <= bp_vaddr) {
+ if (valid_vma(vma, false)) {
+ struct inode *inode;
+ loff_t offset;
- inode = vma->vm_file->f_mapping->host;
- offset = bp_vaddr - vma->vm_start;
- offset += (vma->vm_pgoff << PAGE_SHIFT);
- uprobe = find_uprobe(inode, offset);
+ inode = vma->vm_file->f_mapping->host;
+ offset = bp_vaddr - vma->vm_start;
+ offset += (vma->vm_pgoff << PAGE_SHIFT);
+ uprobe = find_uprobe(inode, offset);
+ }
}
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
current->uprobe_srcu_id = -1;
up_read(&mm->mmap_sem);
+ return uprobe;
+}
+
+/*
+ * Run handler and ask thread to singlestep.
+ * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
+ */
+static void handle_swbp(struct pt_regs *regs)
+{
+ struct uprobe_task *utask;
+ struct uprobe *uprobe;
+ unsigned long bp_vaddr;
+
+ bp_vaddr = uprobe_get_swbp_addr(regs);
+ uprobe = find_active_uprobe(bp_vaddr);
+
if (!uprobe) {
/* No matching uprobe; signal SIGTRAP. */
send_sig(SIGTRAP, current, 0);
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the %22is_swbp%22 info
2012-05-29 19:29 ` [PATCH 4/7] uprobes: teach find_active_uprobe() to provide the "is_swbp" info Oleg Nesterov
@ 2012-06-06 15:10 ` tip-bot for Oleg Nesterov
2012-06-06 16:08 ` [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the "is_swbp" info tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:10 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 183085e74a7faf3654c3a7c243b67b5cb76fa708
Gitweb: http://git.kernel.org/tip/183085e74a7faf3654c3a7c243b67b5cb76fa708
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:29:14 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:56 +0200
uprobes: Teach find_active_uprobe() to provide the %22is_swbp%22 info
A separate patch to simplify the review, and for the
documentation.
The patch adds another "int *is_swbp" argument to
find_active_uprobe(), so far its only caller doesn't use this
info.
With this patch find_active_uprobe() additionally does:
- if find_vma() + ->vm_start check fails, *is_swbp = -EFAULT
- otherwise, if valid_vma() + find_uprobe() fails, it holds
the result of is_swbp_at_addr(), can be negative too. The
latter is only possible if we raced with another thread
which did munmap/etc after we hit this bp.
IOW. If find_active_uprobe(&is_swbp) returns NULL, the caller
can look at is_swbp to figure out whether the current insn is bp
or not, or detect the race with another thread if it is
negative.
Note: I think that performance-wise this change is fine. This
adds is_swbp_at_addr(), but only if we raced with
uprobe_unregister() or if we hit the "normal" int3 but this mm
has uprobes as well. And even in this case the slow
read_opcode() path is very unlikely, this insn recently
triggered do_int3(), __copy_from_user_inatomic() shouldn't fail
in the likely case.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192914.GD8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index eaf4d55..ee3df70 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1489,7 +1489,7 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
return false;
}
-static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
{
struct mm_struct *mm = current->mm;
struct uprobe *uprobe = NULL;
@@ -1497,7 +1497,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
down_read(&mm->mmap_sem);
vma = find_vma(mm, bp_vaddr);
-
if (vma && vma->vm_start <= bp_vaddr) {
if (valid_vma(vma, false)) {
struct inode *inode;
@@ -1508,6 +1507,11 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
offset += (vma->vm_pgoff << PAGE_SHIFT);
uprobe = find_uprobe(inode, offset);
}
+
+ if (!uprobe)
+ *is_swbp = is_swbp_at_addr(mm, bp_vaddr);
+ } else {
+ *is_swbp = -EFAULT;
}
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
@@ -1526,9 +1530,10 @@ static void handle_swbp(struct pt_regs *regs)
struct uprobe_task *utask;
struct uprobe *uprobe;
unsigned long bp_vaddr;
+ int is_swbp;
bp_vaddr = uprobe_get_swbp_addr(regs);
- uprobe = find_active_uprobe(bp_vaddr);
+ uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
/* No matching uprobe; signal SIGTRAP. */
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Change register_for_each_vma() to take mm-%3Emmap_sem for writing
2012-05-29 19:29 ` [PATCH 5/7] uprobes: change register_for_each_vma() to take mm->mmap_sem for writing Oleg Nesterov
@ 2012-06-06 15:11 ` tip-bot for Oleg Nesterov
2012-06-06 16:09 ` [tip:perf/core] uprobes: Change register_for_each_vma() to take mm->mmap_sem " tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:11 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 8d65fee35e63f11f18b658df7c655f674c4bc660
Gitweb: http://git.kernel.org/tip/8d65fee35e63f11f18b658df7c655f674c4bc660
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:29:28 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:56 +0200
uprobes: Change register_for_each_vma() to take mm-%3Emmap_sem for writing
Change register_for_each_vma() to take mm->mmap_sem for writing.
This is a bit unfortunate but hopefully not too bad, this is the
slow path anyway.
This is needed to ensure that find_active_uprobe() can not race
with uprobe_register() which adds the new bp at the same
bp_vaddr, after find_uprobe() fails and before
is_swbp_at_addr_fast() checks the memory.
IOW, this is needed to ensure that if find_active_uprobe()
returns NULL but is_swbp == true, we can safely assume that it
was the "normal" int3 and we should send SIGTRAP.
There is another reason for this change. We are going to replace
uprobes_state->count with MMF_ flags set by register/unregister
and cleared by find_active_uprobe(), and set/clear shouldn't
race with each other.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192928.GE8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ee3df70..a2ed82b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -853,12 +853,12 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
}
mm = vi->mm;
- down_read(&mm->mmap_sem);
+ down_write(&mm->mmap_sem);
vma = find_vma(mm, (unsigned long)vi->vaddr);
if (!vma || !valid_vma(vma, is_register)) {
list_del(&vi->probe_list);
kfree(vi);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
continue;
}
@@ -867,7 +867,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
vaddr != vi->vaddr) {
list_del(&vi->probe_list);
kfree(vi);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
continue;
}
@@ -877,7 +877,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
else
remove_breakpoint(uprobe, mm, vi->vaddr);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
if (is_register) {
if (ret && ret == -EEXIST)
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Teach handle_swbp() to rely on %22is_swbp%22 rather than uprobes_srcu
2012-05-29 19:29 ` [PATCH 6/7] uprobes: teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu Oleg Nesterov
@ 2012-06-06 15:12 ` tip-bot for Oleg Nesterov
2012-06-06 16:10 ` [tip:perf/core] uprobes: Teach handle_swbp() to rely on "is_swbp" " tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:12 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 27e471e0846354376d180c2d2911ec9b94f1e28f
Gitweb: http://git.kernel.org/tip/27e471e0846354376d180c2d2911ec9b94f1e28f
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:29:47 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:57 +0200
uprobes: Teach handle_swbp() to rely on %22is_swbp%22 rather than uprobes_srcu
Currently handle_swbp() assumes that it can't race with
unregister, so it roughly does:
if (find_uprobe(vaddr))
process_uprobe();
else
send_sig(SIGTRAP);
This relies on the not-really-working uprobes_srcu code we are
going to remove, see the next patch.
With this patch we rely on the result of
is_swbp_at_addr(bp_vaddr) if find_uprobe() fails.
If is_swbp == 1, then we hit the normal int3, we should send
SIGTRAP.
If is_swbp == 0, we raced with uprobe_unregister(), we simply
restart this insn again.
The "difficult" case is is_swbp == -EFAULT, when we can't read
this memory. In this case I think we should restart too, and
this is more correct compared to the current code which sends
SIGTRAP.
Ignoring ENOMEM/etc from get_user_pages(), this can only happen
if another thread unmaps this memory before find_active_uprobe()
takes mmap_sem. It would be better to pretend it was unmapped
before this insn was executed, restart, and get SIGSEGV.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192947.GF8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a2ed82b..1f02e3b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1530,14 +1530,26 @@ static void handle_swbp(struct pt_regs *regs)
struct uprobe_task *utask;
struct uprobe *uprobe;
unsigned long bp_vaddr;
- int is_swbp;
+ int uninitialized_var(is_swbp);
bp_vaddr = uprobe_get_swbp_addr(regs);
uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
- /* No matching uprobe; signal SIGTRAP. */
- send_sig(SIGTRAP, current, 0);
+ if (is_swbp > 0) {
+ /* No matching uprobe; signal SIGTRAP. */
+ send_sig(SIGTRAP, current, 0);
+ } else {
+ /*
+ * Either we raced with uprobe_unregister() or we can't
+ * access this memory. The latter is only possible if
+ * another thread plays with our ->mm. In both cases
+ * we can simply restart. If this vma was unmapped we
+ * can pretend this insn was not executed yet and get
+ * the (correct) SIGSEGV after restart.
+ */
+ instruction_pointer_set(regs, bp_vaddr);
+ }
return;
}
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Kill uprobes_srcu/uprobe_srcu_id
2012-05-29 19:30 ` [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-29 23:04 ` Peter Zijlstra
@ 2012-06-06 15:13 ` tip-bot for Oleg Nesterov
2012-06-06 16:10 ` tip-bot for Oleg Nesterov
2 siblings, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 15:13 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 71adc7a026a8c18db0f85d50d28c5f61a0b8d489
Gitweb: http://git.kernel.org/tip/71adc7a026a8c18db0f85d50d28c5f61a0b8d489
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:30:08 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 11:30:57 +0200
uprobes: Kill uprobes_srcu/uprobe_srcu_id
Kill the no longer needed uprobes_srcu/uprobe_srcu_id code.
It doesn't really work anyway. synchronize_srcu() can only
synchronize with the code "inside" the
srcu_read_lock/srcu_read_unlock section, while
uprobe_pre_sstep_notifier() does srcu_read_lock() _after_ we
already hit the breakpoint.
I guess this probably works "in practice". synchronize_srcu() is
slow and it implies synchronize_sched(), and the probed task
enters the non- preemptible section at the start of exception
handler. Still this is not right at least in theory, and
task->uprobe_srcu_id blows task_struct.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529193008.GG8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
include/linux/sched.h | 1 -
kernel/events/uprobes.c | 22 +++-------------------
2 files changed, 3 insertions(+), 20 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6029d8c..6bd1965 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1569,7 +1569,6 @@ struct task_struct {
#endif
#ifdef CONFIG_UPROBES
struct uprobe_task *utask;
- int uprobe_srcu_id;
#endif
};
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1f02e3b..8c5e043 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -38,7 +38,6 @@
#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE
-static struct srcu_struct uprobes_srcu;
static struct rb_root uprobes_tree = RB_ROOT;
static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */
@@ -738,20 +737,14 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
}
/*
- * There could be threads that have hit the breakpoint and are entering the
- * notifier code and trying to acquire the uprobes_treelock. The thread
- * calling delete_uprobe() that is removing the uprobe from the rb_tree can
- * race with these threads and might acquire the uprobes_treelock compared
- * to some of the breakpoint hit threads. In such a case, the breakpoint
- * hit threads will not find the uprobe. The current unregistering thread
- * waits till all other threads have hit a breakpoint, to acquire the
- * uprobes_treelock before the uprobe is removed from the rbtree.
+ * There could be threads that have already hit the breakpoint. They
+ * will recheck the current insn and restart if find_uprobe() fails.
+ * See find_active_uprobe().
*/
static void delete_uprobe(struct uprobe *uprobe)
{
unsigned long flags;
- synchronize_srcu(&uprobes_srcu);
spin_lock_irqsave(&uprobes_treelock, flags);
rb_erase(&uprobe->rb_node, &uprobes_tree);
spin_unlock_irqrestore(&uprobes_treelock, flags);
@@ -1388,9 +1381,6 @@ void uprobe_free_utask(struct task_struct *t)
{
struct uprobe_task *utask = t->utask;
- if (t->uprobe_srcu_id != -1)
- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
-
if (!utask)
return;
@@ -1408,7 +1398,6 @@ void uprobe_free_utask(struct task_struct *t)
void uprobe_copy_process(struct task_struct *t)
{
t->utask = NULL;
- t->uprobe_srcu_id = -1;
}
/*
@@ -1513,9 +1502,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
} else {
*is_swbp = -EFAULT;
}
-
- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
- current->uprobe_srcu_id = -1;
up_read(&mm->mmap_sem);
return uprobe;
@@ -1656,7 +1642,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
utask->state = UTASK_BP_HIT;
set_thread_flag(TIF_UPROBE);
- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
return 1;
}
@@ -1691,7 +1676,6 @@ static int __init init_uprobes(void)
mutex_init(&uprobes_mutex[i]);
mutex_init(&uprobes_mmap_mutex[i]);
}
- init_srcu_struct(&uprobes_srcu);
return register_die_notifier(&uprobe_exception_nb);
}
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-> mm
2012-05-29 19:27 ` [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm Oleg Nesterov
2012-06-06 15:08 ` [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-%3Emm tip-bot for Oleg Nesterov
@ 2012-06-06 16:05 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:05 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: c00b275043adc14d668f36266b890f0c53d46640
Gitweb: http://git.kernel.org/tip/c00b275043adc14d668f36266b890f0c53d46640
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:27:44 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:13:59 +0200
uprobes: Optimize is_swbp_at_addr() for current->mm
Change is_swbp_at_addr() to try to avoid the costly
read_opcode() if mm == current->mm, __copy_from_user_inatomic()
should succeed in the likely case.
Currently this optimization is not important, but we are going
to add more is_swbp_at_addr(current->mm) callers.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192744.GA8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 985be4d..d0f5ec0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -333,10 +333,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
uprobe_opcode_t opcode;
int result;
+ if (current->mm == mm) {
+ pagefault_disable();
+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+ sizeof(opcode));
+ pagefault_enable();
+
+ if (likely(result == 0))
+ goto out;
+ }
+
result = read_opcode(mm, vaddr, &opcode);
if (result)
return result;
-
+out:
if (is_swbp_insn(&opcode))
return 1;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Change read_opcode() to use FOLL_FORCE
2012-05-29 19:27 ` [PATCH 2/7] uprobes: change read_opcode() to use FOLL_FORCE Oleg Nesterov
2012-06-06 15:09 ` [tip:perf/core] uprobes: Change " tip-bot for Oleg Nesterov
@ 2012-06-06 16:06 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:06 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: a3d7bb47937b3a40b9f0c75655e97b3bb6407cbe
Gitweb: http://git.kernel.org/tip/a3d7bb47937b3a40b9f0c75655e97b3bb6407cbe
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:27:59 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:14:49 +0200
uprobes: Change read_opcode() to use FOLL_FORCE
set_orig_insn()->read_opcode() should not fail if the probed
task did mprotect() after uprobe_register(), change it to use
FOLL_FORCE. Without FOLL_WRITE this doesn't have any "side"
effect but allows to read the !VM_READ memory.
There is another reason for this change, we are going to use
is_swbp_at_addr() from handle_swbp() which can race with another
thread doing mprotect().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192759.GB8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d0f5ec0..a0dbc87 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -312,7 +312,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_
void *vaddr_new;
int ret;
- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
if (ret <= 0)
return ret;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Introduce find_active_uprobe() helper
2012-05-29 19:28 ` [PATCH 3/7] uprobes: introduce find_active_uprobe() helper Oleg Nesterov
2012-06-06 15:10 ` [tip:perf/core] uprobes: Introduce " tip-bot for Oleg Nesterov
@ 2012-06-06 16:07 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:07 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 3a9ea0520f38def4a3915b91f82455b749f07d88
Gitweb: http://git.kernel.org/tip/3a9ea0520f38def4a3915b91f82455b749f07d88
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:28:57 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:15:17 +0200
uprobes: Introduce find_active_uprobe() helper
No functional changes. Move the "find uprobe" code from
handle_swbp() to the new helper, find_active_uprobe().
Note: with or without this change, the find-active-uprobe logic
is not exactly right. We can race with another thread which
unmaps the memory with the valid uprobe before we take
mm->mmap_sem. We can't find this uprobe simply because
find_vma() fails. In this case we wrongly assume that this trap
was not caused by uprobe and send the erroneous SIGTRAP. See the
next changes.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192857.GC8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 47 ++++++++++++++++++++++++++++-------------------
1 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a0dbc87..eaf4d55 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1489,38 +1489,47 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
return false;
}
-/*
- * Run handler and ask thread to singlestep.
- * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
- */
-static void handle_swbp(struct pt_regs *regs)
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
{
+ struct mm_struct *mm = current->mm;
+ struct uprobe *uprobe = NULL;
struct vm_area_struct *vma;
- struct uprobe_task *utask;
- struct uprobe *uprobe;
- struct mm_struct *mm;
- unsigned long bp_vaddr;
- uprobe = NULL;
- bp_vaddr = uprobe_get_swbp_addr(regs);
- mm = current->mm;
down_read(&mm->mmap_sem);
vma = find_vma(mm, bp_vaddr);
- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
- struct inode *inode;
- loff_t offset;
+ if (vma && vma->vm_start <= bp_vaddr) {
+ if (valid_vma(vma, false)) {
+ struct inode *inode;
+ loff_t offset;
- inode = vma->vm_file->f_mapping->host;
- offset = bp_vaddr - vma->vm_start;
- offset += (vma->vm_pgoff << PAGE_SHIFT);
- uprobe = find_uprobe(inode, offset);
+ inode = vma->vm_file->f_mapping->host;
+ offset = bp_vaddr - vma->vm_start;
+ offset += (vma->vm_pgoff << PAGE_SHIFT);
+ uprobe = find_uprobe(inode, offset);
+ }
}
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
current->uprobe_srcu_id = -1;
up_read(&mm->mmap_sem);
+ return uprobe;
+}
+
+/*
+ * Run handler and ask thread to singlestep.
+ * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
+ */
+static void handle_swbp(struct pt_regs *regs)
+{
+ struct uprobe_task *utask;
+ struct uprobe *uprobe;
+ unsigned long bp_vaddr;
+
+ bp_vaddr = uprobe_get_swbp_addr(regs);
+ uprobe = find_active_uprobe(bp_vaddr);
+
if (!uprobe) {
/* No matching uprobe; signal SIGTRAP. */
send_sig(SIGTRAP, current, 0);
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the "is_swbp" info
2012-05-29 19:29 ` [PATCH 4/7] uprobes: teach find_active_uprobe() to provide the "is_swbp" info Oleg Nesterov
2012-06-06 15:10 ` [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the %22is_swbp%22 info tip-bot for Oleg Nesterov
@ 2012-06-06 16:08 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:08 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: d790d34653ab20c74034902f5f0889bba807949a
Gitweb: http://git.kernel.org/tip/d790d34653ab20c74034902f5f0889bba807949a
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:29:14 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:15:24 +0200
uprobes: Teach find_active_uprobe() to provide the "is_swbp" info
A separate patch to simplify the review, and for the
documentation.
The patch adds another "int *is_swbp" argument to
find_active_uprobe(), so far its only caller doesn't use this
info.
With this patch find_active_uprobe() additionally does:
- if find_vma() + ->vm_start check fails, *is_swbp = -EFAULT
- otherwise, if valid_vma() + find_uprobe() fails, it holds
the result of is_swbp_at_addr(), can be negative too. The
latter is only possible if we raced with another thread
which did munmap/etc after we hit this bp.
IOW. If find_active_uprobe(&is_swbp) returns NULL, the caller
can look at is_swbp to figure out whether the current insn is bp
or not, or detect the race with another thread if it is
negative.
Note: I think that performance-wise this change is fine. This
adds is_swbp_at_addr(), but only if we raced with
uprobe_unregister() or if we hit the "normal" int3 but this mm
has uprobes as well. And even in this case the slow
read_opcode() path is very unlikely, this insn recently
triggered do_int3(), __copy_from_user_inatomic() shouldn't fail
in the likely case.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192914.GD8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index eaf4d55..ee3df70 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1489,7 +1489,7 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
return false;
}
-static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
{
struct mm_struct *mm = current->mm;
struct uprobe *uprobe = NULL;
@@ -1497,7 +1497,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
down_read(&mm->mmap_sem);
vma = find_vma(mm, bp_vaddr);
-
if (vma && vma->vm_start <= bp_vaddr) {
if (valid_vma(vma, false)) {
struct inode *inode;
@@ -1508,6 +1507,11 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
offset += (vma->vm_pgoff << PAGE_SHIFT);
uprobe = find_uprobe(inode, offset);
}
+
+ if (!uprobe)
+ *is_swbp = is_swbp_at_addr(mm, bp_vaddr);
+ } else {
+ *is_swbp = -EFAULT;
}
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
@@ -1526,9 +1530,10 @@ static void handle_swbp(struct pt_regs *regs)
struct uprobe_task *utask;
struct uprobe *uprobe;
unsigned long bp_vaddr;
+ int is_swbp;
bp_vaddr = uprobe_get_swbp_addr(regs);
- uprobe = find_active_uprobe(bp_vaddr);
+ uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
/* No matching uprobe; signal SIGTRAP. */
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing
2012-05-29 19:29 ` [PATCH 5/7] uprobes: change register_for_each_vma() to take mm->mmap_sem for writing Oleg Nesterov
2012-06-06 15:11 ` [tip:perf/core] uprobes: Change register_for_each_vma() to take mm-%3Emmap_sem " tip-bot for Oleg Nesterov
@ 2012-06-06 16:09 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:09 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 77fc4af1b59d12ab3b1467adf0a5204806853123
Gitweb: http://git.kernel.org/tip/77fc4af1b59d12ab3b1467adf0a5204806853123
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:29:28 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:21:48 +0200
uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing
Change register_for_each_vma() to take mm->mmap_sem for writing.
This is a bit unfortunate but hopefully not too bad, this is the
slow path anyway.
This is needed to ensure that find_active_uprobe() can not race
with uprobe_register() which adds the new bp at the same
bp_vaddr, after find_uprobe() fails and before
is_swbp_at_addr_fast() checks the memory.
IOW, this is needed to ensure that if find_active_uprobe()
returns NULL but is_swbp == true, we can safely assume that it
was the "normal" int3 and we should send SIGTRAP.
There is another reason for this change. We are going to replace
uprobes_state->count with MMF_ flags set by register/unregister
and cleared by find_active_uprobe(), and set/clear shouldn't
race with each other.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192928.GE8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ee3df70..a2ed82b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -853,12 +853,12 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
}
mm = vi->mm;
- down_read(&mm->mmap_sem);
+ down_write(&mm->mmap_sem);
vma = find_vma(mm, (unsigned long)vi->vaddr);
if (!vma || !valid_vma(vma, is_register)) {
list_del(&vi->probe_list);
kfree(vi);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
continue;
}
@@ -867,7 +867,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
vaddr != vi->vaddr) {
list_del(&vi->probe_list);
kfree(vi);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
continue;
}
@@ -877,7 +877,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
else
remove_breakpoint(uprobe, mm, vi->vaddr);
- up_read(&mm->mmap_sem);
+ up_write(&mm->mmap_sem);
mmput(mm);
if (is_register) {
if (ret && ret == -EEXIST)
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu
2012-05-29 19:29 ` [PATCH 6/7] uprobes: teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu Oleg Nesterov
2012-06-06 15:12 ` [tip:perf/core] uprobes: Teach handle_swbp() to rely on %22is_swbp%22 " tip-bot for Oleg Nesterov
@ 2012-06-06 16:10 ` tip-bot for Oleg Nesterov
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:10 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 56bb4cf6475d702d2fb00fc641aa6441097c0330
Gitweb: http://git.kernel.org/tip/56bb4cf6475d702d2fb00fc641aa6441097c0330
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:29:47 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:22:03 +0200
uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu
Currently handle_swbp() assumes that it can't race with
unregister, so it roughly does:
if (find_uprobe(vaddr))
process_uprobe();
else
send_sig(SIGTRAP);
This relies on the not-really-working uprobes_srcu code we are
going to remove, see the next patch.
With this patch we rely on the result of
is_swbp_at_addr(bp_vaddr) if find_uprobe() fails.
If is_swbp == 1, then we hit the normal int3, we should send
SIGTRAP.
If is_swbp == 0, we raced with uprobe_unregister(), we simply
restart this insn again.
The "difficult" case is is_swbp == -EFAULT, when we can't read
this memory. In this case I think we should restart too, and
this is more correct compared to the current code which sends
SIGTRAP.
Ignoring ENOMEM/etc from get_user_pages(), this can only happen
if another thread unmaps this memory before find_active_uprobe()
takes mmap_sem. It would be better to pretend it was unmapped
before this insn was executed, restart, and get SIGSEGV.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529192947.GF8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/events/uprobes.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a2ed82b..1f02e3b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1530,14 +1530,26 @@ static void handle_swbp(struct pt_regs *regs)
struct uprobe_task *utask;
struct uprobe *uprobe;
unsigned long bp_vaddr;
- int is_swbp;
+ int uninitialized_var(is_swbp);
bp_vaddr = uprobe_get_swbp_addr(regs);
uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
- /* No matching uprobe; signal SIGTRAP. */
- send_sig(SIGTRAP, current, 0);
+ if (is_swbp > 0) {
+ /* No matching uprobe; signal SIGTRAP. */
+ send_sig(SIGTRAP, current, 0);
+ } else {
+ /*
+ * Either we raced with uprobe_unregister() or we can't
+ * access this memory. The latter is only possible if
+ * another thread plays with our ->mm. In both cases
+ * we can simply restart. If this vma was unmapped we
+ * can pretend this insn was not executed yet and get
+ * the (correct) SIGSEGV after restart.
+ */
+ instruction_pointer_set(regs, bp_vaddr);
+ }
return;
}
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip:perf/core] uprobes: Kill uprobes_srcu/uprobe_srcu_id
2012-05-29 19:30 ` [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-29 23:04 ` Peter Zijlstra
2012-06-06 15:13 ` [tip:perf/core] uprobes: Kill uprobes_srcu/uprobe_srcu_id tip-bot for Oleg Nesterov
@ 2012-06-06 16:10 ` tip-bot for Oleg Nesterov
2 siblings, 0 replies; 25+ messages in thread
From: tip-bot for Oleg Nesterov @ 2012-06-06 16:10 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, peterz, ananth, anton,
masami.hiramatsu.pt, srikar, tglx, oleg
Commit-ID: 778b032d96909690c19d84f8d17c13be65ed6f8e
Gitweb: http://git.kernel.org/tip/778b032d96909690c19d84f8d17c13be65ed6f8e
Author: Oleg Nesterov <oleg@redhat.com>
AuthorDate: Tue, 29 May 2012 21:30:08 +0200
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 6 Jun 2012 17:22:22 +0200
uprobes: Kill uprobes_srcu/uprobe_srcu_id
Kill the no longer needed uprobes_srcu/uprobe_srcu_id code.
It doesn't really work anyway. synchronize_srcu() can only
synchronize with the code "inside" the
srcu_read_lock/srcu_read_unlock section, while
uprobe_pre_sstep_notifier() does srcu_read_lock() _after_ we
already hit the breakpoint.
I guess this probably works "in practice". synchronize_srcu() is
slow and it implies synchronize_sched(), and the probed task
enters the non- preemptible section at the start of exception
handler. Still this is not right at least in theory, and
task->uprobe_srcu_id blows task_struct.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120529193008.GG8057@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
include/linux/sched.h | 1 -
kernel/events/uprobes.c | 22 +++-------------------
2 files changed, 3 insertions(+), 20 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6029d8c..6bd1965 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1569,7 +1569,6 @@ struct task_struct {
#endif
#ifdef CONFIG_UPROBES
struct uprobe_task *utask;
- int uprobe_srcu_id;
#endif
};
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1f02e3b..8c5e043 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -38,7 +38,6 @@
#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE
-static struct srcu_struct uprobes_srcu;
static struct rb_root uprobes_tree = RB_ROOT;
static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */
@@ -738,20 +737,14 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
}
/*
- * There could be threads that have hit the breakpoint and are entering the
- * notifier code and trying to acquire the uprobes_treelock. The thread
- * calling delete_uprobe() that is removing the uprobe from the rb_tree can
- * race with these threads and might acquire the uprobes_treelock compared
- * to some of the breakpoint hit threads. In such a case, the breakpoint
- * hit threads will not find the uprobe. The current unregistering thread
- * waits till all other threads have hit a breakpoint, to acquire the
- * uprobes_treelock before the uprobe is removed from the rbtree.
+ * There could be threads that have already hit the breakpoint. They
+ * will recheck the current insn and restart if find_uprobe() fails.
+ * See find_active_uprobe().
*/
static void delete_uprobe(struct uprobe *uprobe)
{
unsigned long flags;
- synchronize_srcu(&uprobes_srcu);
spin_lock_irqsave(&uprobes_treelock, flags);
rb_erase(&uprobe->rb_node, &uprobes_tree);
spin_unlock_irqrestore(&uprobes_treelock, flags);
@@ -1388,9 +1381,6 @@ void uprobe_free_utask(struct task_struct *t)
{
struct uprobe_task *utask = t->utask;
- if (t->uprobe_srcu_id != -1)
- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
-
if (!utask)
return;
@@ -1408,7 +1398,6 @@ void uprobe_free_utask(struct task_struct *t)
void uprobe_copy_process(struct task_struct *t)
{
t->utask = NULL;
- t->uprobe_srcu_id = -1;
}
/*
@@ -1513,9 +1502,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
} else {
*is_swbp = -EFAULT;
}
-
- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
- current->uprobe_srcu_id = -1;
up_read(&mm->mmap_sem);
return uprobe;
@@ -1656,7 +1642,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
utask->state = UTASK_BP_HIT;
set_thread_flag(TIF_UPROBE);
- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
return 1;
}
@@ -1691,7 +1676,6 @@ static int __init init_uprobes(void)
mutex_init(&uprobes_mutex[i]);
mutex_init(&uprobes_mmap_mutex[i]);
}
- init_srcu_struct(&uprobes_srcu);
return register_die_notifier(&uprobe_exception_nb);
}
^ permalink raw reply related [flat|nested] 25+ messages in thread
end of thread, other threads:[~2012-06-06 16:11 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-29 19:27 [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-29 19:27 ` [PATCH 1/7] uprobes: optimize is_swbp_at_addr() for current->mm Oleg Nesterov
2012-06-06 15:08 ` [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-%3Emm tip-bot for Oleg Nesterov
2012-06-06 16:05 ` [tip:perf/core] uprobes: Optimize is_swbp_at_addr() for current-> mm tip-bot for Oleg Nesterov
2012-05-29 19:27 ` [PATCH 2/7] uprobes: change read_opcode() to use FOLL_FORCE Oleg Nesterov
2012-06-06 15:09 ` [tip:perf/core] uprobes: Change " tip-bot for Oleg Nesterov
2012-06-06 16:06 ` tip-bot for Oleg Nesterov
2012-05-29 19:28 ` [PATCH 3/7] uprobes: introduce find_active_uprobe() helper Oleg Nesterov
2012-06-06 15:10 ` [tip:perf/core] uprobes: Introduce " tip-bot for Oleg Nesterov
2012-06-06 16:07 ` tip-bot for Oleg Nesterov
2012-05-29 19:29 ` [PATCH 4/7] uprobes: teach find_active_uprobe() to provide the "is_swbp" info Oleg Nesterov
2012-06-06 15:10 ` [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the %22is_swbp%22 info tip-bot for Oleg Nesterov
2012-06-06 16:08 ` [tip:perf/core] uprobes: Teach find_active_uprobe() to provide the "is_swbp" info tip-bot for Oleg Nesterov
2012-05-29 19:29 ` [PATCH 5/7] uprobes: change register_for_each_vma() to take mm->mmap_sem for writing Oleg Nesterov
2012-06-06 15:11 ` [tip:perf/core] uprobes: Change register_for_each_vma() to take mm-%3Emmap_sem " tip-bot for Oleg Nesterov
2012-06-06 16:09 ` [tip:perf/core] uprobes: Change register_for_each_vma() to take mm->mmap_sem " tip-bot for Oleg Nesterov
2012-05-29 19:29 ` [PATCH 6/7] uprobes: teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu Oleg Nesterov
2012-06-06 15:12 ` [tip:perf/core] uprobes: Teach handle_swbp() to rely on %22is_swbp%22 " tip-bot for Oleg Nesterov
2012-06-06 16:10 ` [tip:perf/core] uprobes: Teach handle_swbp() to rely on "is_swbp" " tip-bot for Oleg Nesterov
2012-05-29 19:30 ` [PATCH 7/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Oleg Nesterov
2012-05-29 23:04 ` Peter Zijlstra
2012-05-30 1:51 ` Paul E. McKenney
2012-06-06 15:13 ` [tip:perf/core] uprobes: Kill uprobes_srcu/uprobe_srcu_id tip-bot for Oleg Nesterov
2012-06-06 16:10 ` tip-bot for Oleg Nesterov
2012-05-31 5:40 ` [PATCH 0/7] uprobes: kill uprobes_srcu/uprobe_srcu_id Srikar Dronamraju
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).