linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix
@ 2012-12-31 17:51 Oleg Nesterov
  2012-12-31 17:52 ` [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area() Oleg Nesterov
                   ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:51 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

Hello.

This series fixes the minor bug and cleanups the usage of add_utask()
and xol_alloc_area(). Plus it cleanups the initializaion of ->utask
in handle_swbp() paths.

Anton, this conflicts with your uretprobe patches, but I think we
should do this to avoid the code duplication. IOW, I consider this
series as a minor preparations for uretprobes as well.

Oleg.

 kernel/events/uprobes.c |  150 +++++++++++++++++++++--------------------------
 1 files changed, 68 insertions(+), 82 deletions(-)


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area()
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-07  9:16   ` Anton Arapov
  2013-01-08 11:46   ` Srikar Dronamraju
  2012-12-31 17:52 ` [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area() Oleg Nesterov
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

Move alloc_page() from xol_add_vma() to xol_alloc_area() to cleanup
the code. This separates the memory allocations and consolidates the
-EALREADY cleanups and the error handling.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   32 +++++++++++++-------------------
 1 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index f883813..1456f7d 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1041,22 +1041,14 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
 /* Slot allocation for XOL */
 static int xol_add_vma(struct xol_area *area)
 {
-	struct mm_struct *mm;
-	int ret;
-
-	area->page = alloc_page(GFP_HIGHUSER);
-	if (!area->page)
-		return -ENOMEM;
-
-	ret = -EALREADY;
-	mm = current->mm;
+	struct mm_struct *mm = current->mm;
+	int ret = -EALREADY;
 
 	down_write(&mm->mmap_sem);
 	if (mm->uprobes_state.xol_area)
 		goto fail;
 
 	ret = -ENOMEM;
-
 	/* Try to map as high as possible, this is only a hint. */
 	area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0);
 	if (area->vaddr & ~PAGE_MASK) {
@@ -1072,11 +1064,8 @@ static int xol_add_vma(struct xol_area *area)
 	smp_wmb();	/* pairs with get_xol_area() */
 	mm->uprobes_state.xol_area = area;
 	ret = 0;
-
-fail:
+ fail:
 	up_write(&mm->mmap_sem);
-	if (ret)
-		__free_page(area->page);
 
 	return ret;
 }
@@ -1104,21 +1093,26 @@ static struct xol_area *xol_alloc_area(void)
 
 	area = kzalloc(sizeof(*area), GFP_KERNEL);
 	if (unlikely(!area))
-		return NULL;
+		goto out;
 
 	area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
-
 	if (!area->bitmap)
-		goto fail;
+		goto free_area;
+
+	area->page = area->page = alloc_page(GFP_HIGHUSER);
+	if (!area->page)
+		goto free_bitmap;
 
 	init_waitqueue_head(&area->wq);
 	if (!xol_add_vma(area))
 		return area;
 
-fail:
+	__free_page(area->page);
+ free_bitmap:
 	kfree(area->bitmap);
+ free_area:
 	kfree(area);
-
+ out:
 	return get_xol_area(current->mm);
 }
 
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area()
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
  2012-12-31 17:52 ` [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area() Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-08 11:55   ` Srikar Dronamraju
  2013-01-09 10:16   ` Anton Arapov
  2012-12-31 17:52 ` [PATCH 3/7] uprobes: Turn add_utask() into get_utask() Oleg Nesterov
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

Currently only xol_get_insn_slot() does get_xol_area() + xol_alloc_area(),
but this will have more users and we do not want to copy-and-paste this
code. This patch simply moves xol_alloc_area() into get_xol_area() to
simplify the current and future code.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   38 ++++++++++++++++----------------------
 1 files changed, 16 insertions(+), 22 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1456f7d..ef81162 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1070,27 +1070,21 @@ static int xol_add_vma(struct xol_area *area)
 	return ret;
 }
 
-static struct xol_area *get_xol_area(struct mm_struct *mm)
-{
-	struct xol_area *area;
-
-	area = mm->uprobes_state.xol_area;
-	smp_read_barrier_depends();	/* pairs with wmb in xol_add_vma() */
-
-	return area;
-}
-
 /*
- * xol_alloc_area - Allocate process's xol_area.
- * This area will be used for storing instructions for execution out of
- * line.
+ * get_alloc_area - Allocate process's xol_area if necessary.
+ * This area will be used for storing instructions for execution out of line.
  *
  * Returns the allocated area or NULL.
  */
-static struct xol_area *xol_alloc_area(void)
+static struct xol_area *get_xol_area(void)
 {
+	struct mm_struct *mm = current->mm;
 	struct xol_area *area;
 
+	area = mm->uprobes_state.xol_area;
+	if (area)
+		goto ret;
+
 	area = kzalloc(sizeof(*area), GFP_KERNEL);
 	if (unlikely(!area))
 		goto out;
@@ -1113,7 +1107,10 @@ static struct xol_area *xol_alloc_area(void)
  free_area:
 	kfree(area);
  out:
-	return get_xol_area(current->mm);
+	area = mm->uprobes_state.xol_area;
+ ret:
+	smp_read_barrier_depends();     /* pairs with wmb in xol_add_vma() */
+	return area;
 }
 
 /*
@@ -1189,14 +1186,11 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot
 	unsigned long offset;
 	void *vaddr;
 
-	area = get_xol_area(current->mm);
-	if (!area) {
-		area = xol_alloc_area();
-		if (!area)
-			return 0;
-	}
-	current->utask->xol_vaddr = xol_take_insn_slot(area);
+	area = get_xol_area();
+	if (!area)
+		return 0;
 
+	current->utask->xol_vaddr = xol_take_insn_slot(area);
 	/*
 	 * Initialize the slot if xol_vaddr points to valid
 	 * instruction slot.
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/7] uprobes: Turn add_utask() into get_utask()
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
  2012-12-31 17:52 ` [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area() Oleg Nesterov
  2012-12-31 17:52 ` [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area() Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-08 11:57   ` Srikar Dronamraju
  2012-12-31 17:52 ` [PATCH 4/7] uprobes: Do not play with utask in xol_get_insn_slot() Oleg Nesterov
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

Rename add_utask() into get_utask() and change it to allocate on
demand to simplify the caller. Like get_xol_area() it will have
more users.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   27 +++++++++------------------
 1 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ef81162..b09b3ba 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1290,23 +1290,18 @@ void uprobe_copy_process(struct task_struct *t)
 }
 
 /*
- * Allocate a uprobe_task object for the task.
- * Called when the thread hits a breakpoint for the first time.
+ * Allocate a uprobe_task object for the task if if necessary.
+ * Called when the thread hits a breakpoint.
  *
  * Returns:
  * - pointer to new uprobe_task on success
  * - NULL otherwise
  */
-static struct uprobe_task *add_utask(void)
+static struct uprobe_task *get_utask(void)
 {
-	struct uprobe_task *utask;
-
-	utask = kzalloc(sizeof *utask, GFP_KERNEL);
-	if (unlikely(!utask))
-		return NULL;
-
-	current->utask = utask;
-	return utask;
+	if (!current->utask)
+		current->utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
+	return current->utask;
 }
 
 /* Prepare to single-step probed instruction out of line. */
@@ -1505,13 +1500,9 @@ static void handle_swbp(struct pt_regs *regs)
 	if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
 		goto out;
 
-	utask = current->utask;
-	if (!utask) {
-		utask = add_utask();
-		/* Cannot allocate; re-execute the instruction. */
-		if (!utask)
-			goto out;
-	}
+	utask = get_utask();
+	if (!utask)
+		goto out;	/* re-execute the instruction. */
 
 	handler_chain(uprobe, regs);
 	if (can_skip_sstep(uprobe, regs))
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 4/7] uprobes: Do not play with utask in xol_get_insn_slot()
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
                   ` (2 preceding siblings ...)
  2012-12-31 17:52 ` [PATCH 3/7] uprobes: Turn add_utask() into get_utask() Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-08 12:07   ` Srikar Dronamraju
  2012-12-31 17:52 ` [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout() Oleg Nesterov
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

pre_ssout()->xol_get_insn_slot() path is confusing and buggy. This patch
cleanups the code, the next one fixes the bug.

Change xol_get_insn_slot() to only allocate the slot and do nothing more,
move the initialization of utask->xol_vaddr/vaddr into pre_ssout().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   37 +++++++++++++++++++++----------------
 1 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index b09b3ba..2ed6239 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1176,30 +1176,26 @@ static unsigned long xol_take_insn_slot(struct xol_area *area)
 }
 
 /*
- * xol_get_insn_slot - If was not allocated a slot, then
- * allocate a slot.
+ * xol_get_insn_slot - allocate a slot for xol.
  * Returns the allocated slot address or 0.
  */
-static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot_addr)
+static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 {
 	struct xol_area *area;
 	unsigned long offset;
+	unsigned long xol_vaddr;
 	void *vaddr;
 
 	area = get_xol_area();
 	if (!area)
 		return 0;
 
-	current->utask->xol_vaddr = xol_take_insn_slot(area);
-	/*
-	 * Initialize the slot if xol_vaddr points to valid
-	 * instruction slot.
-	 */
-	if (unlikely(!current->utask->xol_vaddr))
+	xol_vaddr = xol_take_insn_slot(area);
+	if (unlikely(!xol_vaddr))
 		return 0;
 
-	current->utask->vaddr = slot_addr;
-	offset = current->utask->xol_vaddr & ~PAGE_MASK;
+	/* Initialize the slot */
+	offset = xol_vaddr & ~PAGE_MASK;
 	vaddr = kmap_atomic(area->page);
 	memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES);
 	kunmap_atomic(vaddr);
@@ -1209,7 +1205,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot
 	 */
 	flush_dcache_page(area->page);
 
-	return current->utask->xol_vaddr;
+	return xol_vaddr;
 }
 
 /*
@@ -1306,12 +1302,21 @@ static struct uprobe_task *get_utask(void)
 
 /* Prepare to single-step probed instruction out of line. */
 static int
-pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long vaddr)
+pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 {
-	if (xol_get_insn_slot(uprobe, vaddr) && !arch_uprobe_pre_xol(&uprobe->arch, regs))
-		return 0;
+	struct uprobe_task *utask;
+	unsigned long xol_vaddr;
+
+	utask = current->utask;
+
+	xol_vaddr = xol_get_insn_slot(uprobe);
+	if (!xol_vaddr)
+		return -ENOMEM;
+
+	utask->xol_vaddr = xol_vaddr;
+	utask->vaddr = bp_vaddr;
 
-	return -EFAULT;
+	return arch_uprobe_pre_xol(&uprobe->arch, regs);
 }
 
 /*
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout()
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
                   ` (3 preceding siblings ...)
  2012-12-31 17:52 ` [PATCH 4/7] uprobes: Do not play with utask in xol_get_insn_slot() Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-08 12:13   ` Srikar Dronamraju
  2012-12-31 17:52 ` [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary Oleg Nesterov
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

pre_ssout() should do xol_free_insn_slot() if arch_uprobe_pre_xol()
fails, otherwise nobody will free the allocated slot.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 2ed6239..bd94d2c 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1306,6 +1306,7 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 {
 	struct uprobe_task *utask;
 	unsigned long xol_vaddr;
+	int err;
 
 	utask = current->utask;
 
@@ -1316,7 +1317,13 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 	utask->xol_vaddr = xol_vaddr;
 	utask->vaddr = bp_vaddr;
 
-	return arch_uprobe_pre_xol(&uprobe->arch, regs);
+	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
+	if (unlikely(err)) {
+		xol_free_insn_slot(current);
+		return err;
+	}
+
+	return 0;
 }
 
 /*
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
                   ` (4 preceding siblings ...)
  2012-12-31 17:52 ` [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout() Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-08 12:20   ` Srikar Dronamraju
  2012-12-31 17:52 ` [PATCH 7/7] uprobes: Kill the bogus IS_ERR_VALUE(xol_vaddr) check Oleg Nesterov
  2013-01-09 10:25 ` [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Anton Arapov
  7 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

handle_swbp() does get_utask() before can_skip_sstep() for no reason,
we do not need ->utask if can_skip_sstep() succeeds.

Move get_utask() to pre_ssout() who actually starts to use it. Move
the initialization of utask->active_uprobe/state as well. This way
the whole initialization is consolidated in pre_ssout().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   16 ++++++----------
 1 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index bd94d2c..ad1245d 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1308,7 +1308,9 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 	unsigned long xol_vaddr;
 	int err;
 
-	utask = current->utask;
+	utask = get_utask();
+	if (!utask)
+		return -ENOMEM;
 
 	xol_vaddr = xol_get_insn_slot(uprobe);
 	if (!xol_vaddr)
@@ -1323,6 +1325,8 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 		return err;
 	}
 
+	utask->active_uprobe = uprobe;
+	utask->state = UTASK_SSTEP;
 	return 0;
 }
 
@@ -1474,7 +1478,6 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
  */
 static void handle_swbp(struct pt_regs *regs)
 {
-	struct uprobe_task *utask;
 	struct uprobe *uprobe;
 	unsigned long bp_vaddr;
 	int uninitialized_var(is_swbp);
@@ -1512,19 +1515,12 @@ static void handle_swbp(struct pt_regs *regs)
 	if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
 		goto out;
 
-	utask = get_utask();
-	if (!utask)
-		goto out;	/* re-execute the instruction. */
-
 	handler_chain(uprobe, regs);
 	if (can_skip_sstep(uprobe, regs))
 		goto out;
 
-	if (!pre_ssout(uprobe, regs, bp_vaddr)) {
-		utask->active_uprobe = uprobe;
-		utask->state = UTASK_SSTEP;
+	if (!pre_ssout(uprobe, regs, bp_vaddr))
 		return;
-	}
 
 	/* can_skip_sstep() succeeded, or restart if can't singlestep */
 out:
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 7/7] uprobes: Kill the bogus IS_ERR_VALUE(xol_vaddr) check
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
                   ` (5 preceding siblings ...)
  2012-12-31 17:52 ` [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary Oleg Nesterov
@ 2012-12-31 17:52 ` Oleg Nesterov
  2013-01-08 12:23   ` Srikar Dronamraju
  2013-01-09 10:25 ` [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Anton Arapov
  7 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2012-12-31 17:52 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, Frank Eigler,
	Josh Stone, Suzuki K. Poulose, linux-kernel

utask->xol_vaddr is either zero or valid, remove the bogus
IS_ERR_VALUE() check in xol_free_insn_slot().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ad1245d..ed4fcbe 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1223,8 +1223,7 @@ static void xol_free_insn_slot(struct task_struct *tsk)
 		return;
 
 	slot_addr = tsk->utask->xol_vaddr;
-
-	if (unlikely(!slot_addr || IS_ERR_VALUE(slot_addr)))
+	if (unlikely(!slot_addr))
 		return;
 
 	area = tsk->mm->uprobes_state.xol_area;
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area()
  2012-12-31 17:52 ` [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area() Oleg Nesterov
@ 2013-01-07  9:16   ` Anton Arapov
  2013-01-07 16:11     ` Oleg Nesterov
  2013-01-08 11:46   ` Srikar Dronamraju
  1 sibling, 1 reply; 25+ messages in thread
From: Anton Arapov @ 2013-01-07  9:16 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju,
	Ananth N Mavinakayanahalli, Frank Eigler, Josh Stone,
	Suzuki K. Poulose, linux-kernel

On Mon, Dec 31, 2012 at 06:52:12PM +0100, Oleg Nesterov wrote:
> Move alloc_page() from xol_add_vma() to xol_alloc_area() to cleanup
> the code. This separates the memory allocations and consolidates the
> -EALREADY cleanups and the error handling.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
>  kernel/events/uprobes.c |   32 +++++++++++++-------------------
>  1 files changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index f883813..1456f7d 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1104,21 +1093,26 @@ static struct xol_area *xol_alloc_area(void)
>  
>  	area = kzalloc(sizeof(*area), GFP_KERNEL);
>  	if (unlikely(!area))
> -		return NULL;
> +		goto out;
>  
>  	area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
> -
>  	if (!area->bitmap)
> -		goto fail;
> +		goto free_area;
> +
> +	area->page = area->page = alloc_page(GFP_HIGHUSER);

fyi: didn't review this patch set yet, just caught the string above. ;)

Anton.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area()
  2013-01-07  9:16   ` Anton Arapov
@ 2013-01-07 16:11     ` Oleg Nesterov
  0 siblings, 0 replies; 25+ messages in thread
From: Oleg Nesterov @ 2013-01-07 16:11 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju,
	Ananth N Mavinakayanahalli, Frank Eigler, Josh Stone,
	Suzuki K. Poulose, linux-kernel

On 01/07, Anton Arapov wrote:
>
> On Mon, Dec 31, 2012 at 06:52:12PM +0100, Oleg Nesterov wrote:
> > -		goto fail;
> > +		goto free_area;
> > +
> > +	area->page = area->page = alloc_page(GFP_HIGHUSER);
>
> fyi: didn't review this patch set yet, just caught the string above. ;)

OOPS, thanks, will fix.

Oleg.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area()
  2012-12-31 17:52 ` [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area() Oleg Nesterov
  2013-01-07  9:16   ` Anton Arapov
@ 2013-01-08 11:46   ` Srikar Dronamraju
  2013-01-08 17:58     ` Oleg Nesterov
  1 sibling, 1 reply; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 11:46 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:12]:

> Move alloc_page() from xol_add_vma() to xol_alloc_area() to cleanup
> the code. This separates the memory allocations and consolidates the
> -EALREADY cleanups and the error handling.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

(One simple check below)

Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>


> ---
>  kernel/events/uprobes.c |   32 +++++++++++++-------------------
>  1 files changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index f883813..1456f7d 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1041,22 +1041,14 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
>  /* Slot allocation for XOL */
>  static int xol_add_vma(struct xol_area *area)
>  {
> -	struct mm_struct *mm;
> -	int ret;
> -
> -	area->page = alloc_page(GFP_HIGHUSER);
> -	if (!area->page)
> -		return -ENOMEM;
> -
> -	ret = -EALREADY;
> -	mm = current->mm;
> +	struct mm_struct *mm = current->mm;
> +	int ret = -EALREADY;
> 
>  	down_write(&mm->mmap_sem);
>  	if (mm->uprobes_state.xol_area)
>  		goto fail;
> 
>  	ret = -ENOMEM;
> -
>  	/* Try to map as high as possible, this is only a hint. */
>  	area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0);
>  	if (area->vaddr & ~PAGE_MASK) {
> @@ -1072,11 +1064,8 @@ static int xol_add_vma(struct xol_area *area)
>  	smp_wmb();	/* pairs with get_xol_area() */
>  	mm->uprobes_state.xol_area = area;
>  	ret = 0;
> -
> -fail:
> + fail:

Not sure if the space before label is intentional?
Its true of other labels below also.

>  	up_write(&mm->mmap_sem);
> -	if (ret)
> -		__free_page(area->page);
> 
>  	return ret;
>  }
> @@ -1104,21 +1093,26 @@ static struct xol_area *xol_alloc_area(void)
> 
>  	area = kzalloc(sizeof(*area), GFP_KERNEL);
>  	if (unlikely(!area))
> -		return NULL;
> +		goto out;
> 
>  	area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
> -
>  	if (!area->bitmap)
> -		goto fail;
> +		goto free_area;
> +
> +	area->page = area->page = alloc_page(GFP_HIGHUSER);
> +	if (!area->page)
> +		goto free_bitmap;
> 
>  	init_waitqueue_head(&area->wq);
>  	if (!xol_add_vma(area))
>  		return area;
> 
> -fail:
> +	__free_page(area->page);
> + free_bitmap:
>  	kfree(area->bitmap);
> + free_area:
>  	kfree(area);
> -
> + out:
>  	return get_xol_area(current->mm);
>  }
> 
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area()
  2012-12-31 17:52 ` [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area() Oleg Nesterov
@ 2013-01-08 11:55   ` Srikar Dronamraju
  2013-01-09 10:16   ` Anton Arapov
  1 sibling, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 11:55 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:16]:

> Currently only xol_get_insn_slot() does get_xol_area() + xol_alloc_area(),
> but this will have more users and we do not want to copy-and-paste this
> code. This patch simply moves xol_alloc_area() into get_xol_area() to
> simplify the current and future code.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

> ---
>  kernel/events/uprobes.c |   38 ++++++++++++++++----------------------
>  1 files changed, 16 insertions(+), 22 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 1456f7d..ef81162 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1070,27 +1070,21 @@ static int xol_add_vma(struct xol_area *area)
>  	return ret;
>  }
> 
> -static struct xol_area *get_xol_area(struct mm_struct *mm)
> -{
> -	struct xol_area *area;
> -
> -	area = mm->uprobes_state.xol_area;
> -	smp_read_barrier_depends();	/* pairs with wmb in xol_add_vma() */
> -
> -	return area;
> -}
> -
>  /*
> - * xol_alloc_area - Allocate process's xol_area.
> - * This area will be used for storing instructions for execution out of
> - * line.
> + * get_alloc_area - Allocate process's xol_area if necessary.
> + * This area will be used for storing instructions for execution out of line.
>   *
>   * Returns the allocated area or NULL.
>   */
> -static struct xol_area *xol_alloc_area(void)
> +static struct xol_area *get_xol_area(void)
>  {
> +	struct mm_struct *mm = current->mm;
>  	struct xol_area *area;
> 
> +	area = mm->uprobes_state.xol_area;
> +	if (area)
> +		goto ret;
> +
>  	area = kzalloc(sizeof(*area), GFP_KERNEL);
>  	if (unlikely(!area))
>  		goto out;
> @@ -1113,7 +1107,10 @@ static struct xol_area *xol_alloc_area(void)
>   free_area:
>  	kfree(area);
>   out:
> -	return get_xol_area(current->mm);
> +	area = mm->uprobes_state.xol_area;
> + ret:
> +	smp_read_barrier_depends();     /* pairs with wmb in xol_add_vma() */
> +	return area;
>  }
> 
>  /*
> @@ -1189,14 +1186,11 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot
>  	unsigned long offset;
>  	void *vaddr;
> 
> -	area = get_xol_area(current->mm);
> -	if (!area) {
> -		area = xol_alloc_area();
> -		if (!area)
> -			return 0;
> -	}
> -	current->utask->xol_vaddr = xol_take_insn_slot(area);
> +	area = get_xol_area();
> +	if (!area)
> +		return 0;
> 
> +	current->utask->xol_vaddr = xol_take_insn_slot(area);
>  	/*
>  	 * Initialize the slot if xol_vaddr points to valid
>  	 * instruction slot.
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/7] uprobes: Turn add_utask() into get_utask()
  2012-12-31 17:52 ` [PATCH 3/7] uprobes: Turn add_utask() into get_utask() Oleg Nesterov
@ 2013-01-08 11:57   ` Srikar Dronamraju
  0 siblings, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 11:57 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:20]:

> Rename add_utask() into get_utask() and change it to allocate on
> demand to simplify the caller. Like get_xol_area() it will have
> more users.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

> ---
>  kernel/events/uprobes.c |   27 +++++++++------------------
>  1 files changed, 9 insertions(+), 18 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index ef81162..b09b3ba 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1290,23 +1290,18 @@ void uprobe_copy_process(struct task_struct *t)
>  }
> 
>  /*
> - * Allocate a uprobe_task object for the task.
> - * Called when the thread hits a breakpoint for the first time.
> + * Allocate a uprobe_task object for the task if if necessary.
> + * Called when the thread hits a breakpoint.
>   *
>   * Returns:
>   * - pointer to new uprobe_task on success
>   * - NULL otherwise
>   */
> -static struct uprobe_task *add_utask(void)
> +static struct uprobe_task *get_utask(void)
>  {
> -	struct uprobe_task *utask;
> -
> -	utask = kzalloc(sizeof *utask, GFP_KERNEL);
> -	if (unlikely(!utask))
> -		return NULL;
> -
> -	current->utask = utask;
> -	return utask;
> +	if (!current->utask)
> +		current->utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
> +	return current->utask;
>  }
> 
>  /* Prepare to single-step probed instruction out of line. */
> @@ -1505,13 +1500,9 @@ static void handle_swbp(struct pt_regs *regs)
>  	if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
>  		goto out;
> 
> -	utask = current->utask;
> -	if (!utask) {
> -		utask = add_utask();
> -		/* Cannot allocate; re-execute the instruction. */
> -		if (!utask)
> -			goto out;
> -	}
> +	utask = get_utask();
> +	if (!utask)
> +		goto out;	/* re-execute the instruction. */
> 
>  	handler_chain(uprobe, regs);
>  	if (can_skip_sstep(uprobe, regs))
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 4/7] uprobes: Do not play with utask in xol_get_insn_slot()
  2012-12-31 17:52 ` [PATCH 4/7] uprobes: Do not play with utask in xol_get_insn_slot() Oleg Nesterov
@ 2013-01-08 12:07   ` Srikar Dronamraju
  0 siblings, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 12:07 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:23]:

> pre_ssout()->xol_get_insn_slot() path is confusing and buggy. This patch
> cleanups the code, the next one fixes the bug.
> 
> Change xol_get_insn_slot() to only allocate the slot and do nothing more,
> move the initialization of utask->xol_vaddr/vaddr into pre_ssout().
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

> ---
>  kernel/events/uprobes.c |   37 +++++++++++++++++++++----------------
>  1 files changed, 21 insertions(+), 16 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index b09b3ba..2ed6239 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1176,30 +1176,26 @@ static unsigned long xol_take_insn_slot(struct xol_area *area)
>  }
> 
>  /*
> - * xol_get_insn_slot - If was not allocated a slot, then
> - * allocate a slot.
> + * xol_get_insn_slot - allocate a slot for xol.
>   * Returns the allocated slot address or 0.
>   */
> -static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot_addr)
> +static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
>  {
>  	struct xol_area *area;
>  	unsigned long offset;
> +	unsigned long xol_vaddr;
>  	void *vaddr;
> 
>  	area = get_xol_area();
>  	if (!area)
>  		return 0;
> 
> -	current->utask->xol_vaddr = xol_take_insn_slot(area);
> -	/*
> -	 * Initialize the slot if xol_vaddr points to valid
> -	 * instruction slot.
> -	 */
> -	if (unlikely(!current->utask->xol_vaddr))
> +	xol_vaddr = xol_take_insn_slot(area);
> +	if (unlikely(!xol_vaddr))
>  		return 0;
> 
> -	current->utask->vaddr = slot_addr;
> -	offset = current->utask->xol_vaddr & ~PAGE_MASK;
> +	/* Initialize the slot */
> +	offset = xol_vaddr & ~PAGE_MASK;
>  	vaddr = kmap_atomic(area->page);
>  	memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES);
>  	kunmap_atomic(vaddr);
> @@ -1209,7 +1205,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot
>  	 */
>  	flush_dcache_page(area->page);
> 
> -	return current->utask->xol_vaddr;
> +	return xol_vaddr;
>  }
> 
>  /*
> @@ -1306,12 +1302,21 @@ static struct uprobe_task *get_utask(void)
> 
>  /* Prepare to single-step probed instruction out of line. */
>  static int
> -pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long vaddr)
> +pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
>  {
> -	if (xol_get_insn_slot(uprobe, vaddr) && !arch_uprobe_pre_xol(&uprobe->arch, regs))
> -		return 0;
> +	struct uprobe_task *utask;
> +	unsigned long xol_vaddr;
> +
> +	utask = current->utask;
> +
> +	xol_vaddr = xol_get_insn_slot(uprobe);
> +	if (!xol_vaddr)
> +		return -ENOMEM;
> +
> +	utask->xol_vaddr = xol_vaddr;
> +	utask->vaddr = bp_vaddr;
> 
> -	return -EFAULT;
> +	return arch_uprobe_pre_xol(&uprobe->arch, regs);
>  }
> 
>  /*
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout()
  2012-12-31 17:52 ` [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout() Oleg Nesterov
@ 2013-01-08 12:13   ` Srikar Dronamraju
  2013-01-08 17:44     ` Oleg Nesterov
  0 siblings, 1 reply; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 12:13 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:26]:

> pre_ssout() should do xol_free_insn_slot() if arch_uprobe_pre_xol()
> fails, otherwise nobody will free the allocated slot.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

(one nit below)
> ---
>  kernel/events/uprobes.c |    9 ++++++++-
>  1 files changed, 8 insertions(+), 1 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 2ed6239..bd94d2c 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1306,6 +1306,7 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
>  {
>  	struct uprobe_task *utask;
>  	unsigned long xol_vaddr;
> +	int err;
> 
>  	utask = current->utask;
> 
> @@ -1316,7 +1317,13 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
>  	utask->xol_vaddr = xol_vaddr;
>  	utask->vaddr = bp_vaddr;
> 
> -	return arch_uprobe_pre_xol(&uprobe->arch, regs);
> +	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
> +	if (unlikely(err)) {
> +		xol_free_insn_slot(current);
> +		return err;
> +	}
> +
> +	return 0;
>  }

Nit: we could reduce a line or two with

	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
	if (unlikely(err))
		xol_free_insn_slot(current);

	return err;
> 
>  /*
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary
  2012-12-31 17:52 ` [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary Oleg Nesterov
@ 2013-01-08 12:20   ` Srikar Dronamraju
  2013-01-08 18:13     ` Oleg Nesterov
  0 siblings, 1 reply; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 12:20 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:29]:

> handle_swbp() does get_utask() before can_skip_sstep() for no reason,
> we do not need ->utask if can_skip_sstep() succeeds.
> 
> Move get_utask() to pre_ssout() who actually starts to use it. Move
> the initialization of utask->active_uprobe/state as well. This way
> the whole initialization is consolidated in pre_ssout().
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
>  kernel/events/uprobes.c |   16 ++++++----------
>  1 files changed, 6 insertions(+), 10 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index bd94d2c..ad1245d 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1308,7 +1308,9 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
>  	unsigned long xol_vaddr;
>  	int err;
> 
> -	utask = current->utask;
> +	utask = get_utask();
> +	if (!utask)
> +		return -ENOMEM;
> 
>  	xol_vaddr = xol_get_insn_slot(uprobe);
>  	if (!xol_vaddr)
> @@ -1323,6 +1325,8 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
>  		return err;
>  	}
> 
> +	utask->active_uprobe = uprobe;
> +	utask->state = UTASK_SSTEP;
>  	return 0;
>  }
> 
> @@ -1474,7 +1478,6 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
>   */
>  static void handle_swbp(struct pt_regs *regs)
>  {
> -	struct uprobe_task *utask;
>  	struct uprobe *uprobe;
>  	unsigned long bp_vaddr;
>  	int uninitialized_var(is_swbp);
> @@ -1512,19 +1515,12 @@ static void handle_swbp(struct pt_regs *regs)
>  	if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
>  		goto out;
> 
> -	utask = get_utask();
> -	if (!utask)
> -		goto out;	/* re-execute the instruction. */
> -


If get_utask fails with the above change, Dont we end up calling
handler_chain twice(or more)?. I think this is probably true with
previous patch too.

>  	handler_chain(uprobe, regs);
>  	if (can_skip_sstep(uprobe, regs))
>  		goto out;
> 
> -	if (!pre_ssout(uprobe, regs, bp_vaddr)) {
> -		utask->active_uprobe = uprobe;
> -		utask->state = UTASK_SSTEP;
> +	if (!pre_ssout(uprobe, regs, bp_vaddr))
>  		return;
> -	}
> 
>  	/* can_skip_sstep() succeeded, or restart if can't singlestep */
>  out:
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 7/7] uprobes: Kill the bogus IS_ERR_VALUE(xol_vaddr) check
  2012-12-31 17:52 ` [PATCH 7/7] uprobes: Kill the bogus IS_ERR_VALUE(xol_vaddr) check Oleg Nesterov
@ 2013-01-08 12:23   ` Srikar Dronamraju
  0 siblings, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-08 12:23 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:32]:

> utask->xol_vaddr is either zero or valid, remove the bogus
> IS_ERR_VALUE() check in xol_free_insn_slot().
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

> ---
>  kernel/events/uprobes.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index ad1245d..ed4fcbe 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1223,8 +1223,7 @@ static void xol_free_insn_slot(struct task_struct *tsk)
>  		return;
> 
>  	slot_addr = tsk->utask->xol_vaddr;
> -
> -	if (unlikely(!slot_addr || IS_ERR_VALUE(slot_addr)))
> +	if (unlikely(!slot_addr))
>  		return;
> 
>  	area = tsk->mm->uprobes_state.xol_area;
> -- 
> 1.5.5.1
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout()
  2013-01-08 12:13   ` Srikar Dronamraju
@ 2013-01-08 17:44     ` Oleg Nesterov
  2013-01-10 12:48       ` Srikar Dronamraju
  0 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2013-01-08 17:44 UTC (permalink / raw)
  To: Srikar Dronamraju
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

On 01/08, Srikar Dronamraju wrote:
>
> * Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:26]:
>
> > pre_ssout() should do xol_free_insn_slot() if arch_uprobe_pre_xol()
> > fails, otherwise nobody will free the allocated slot.
> >
> > Signed-off-by: Oleg Nesterov <oleg@redhat.com>
>
> Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

Thanks!

> (one nit below)
> ...
> > @@ -1316,7 +1317,13 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
> >  	utask->xol_vaddr = xol_vaddr;
> >  	utask->vaddr = bp_vaddr;
> >
> > -	return arch_uprobe_pre_xol(&uprobe->arch, regs);
> > +	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
> > +	if (unlikely(err)) {
> > +		xol_free_insn_slot(current);
> > +		return err;
> > +	}
> > +
> > +	return 0;
> >  }
>
> Nit: we could reduce a line or two with
>
> 	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
> 	if (unlikely(err))
> 		xol_free_insn_slot(current);
>
> 	return err;

Yes, but this is also preparation for the next patch which adds more
code after arch_uprobe_pre_xol() == 0.

Oleg.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area()
  2013-01-08 11:46   ` Srikar Dronamraju
@ 2013-01-08 17:58     ` Oleg Nesterov
  2013-01-09 17:44       ` Srikar Dronamraju
  0 siblings, 1 reply; 25+ messages in thread
From: Oleg Nesterov @ 2013-01-08 17:58 UTC (permalink / raw)
  To: Srikar Dronamraju
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

On 01/08, Srikar Dronamraju wrote:
>
> (One simple check below)
>
> Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>

Thanks,

> > @@ -1072,11 +1064,8 @@ static int xol_add_vma(struct xol_area *area)
> >  	smp_wmb();	/* pairs with get_xol_area() */
> >  	mm->uprobes_state.xol_area = area;
> >  	ret = 0;
> > -
> > -fail:
> > + fail:
>
> Not sure if the space before label is intentional?
> Its true of other labels below also.

Yes, this was intentional although almost subconscious.

Personally I prefer to add a space before the label, this helps
/usr/bin/diff to not confuse this label with the function name.

But I can stop this if you dislike.

Oleg.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary
  2013-01-08 12:20   ` Srikar Dronamraju
@ 2013-01-08 18:13     ` Oleg Nesterov
  0 siblings, 0 replies; 25+ messages in thread
From: Oleg Nesterov @ 2013-01-08 18:13 UTC (permalink / raw)
  To: Srikar Dronamraju
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

On 01/08, Srikar Dronamraju wrote:
>
> * Oleg Nesterov <oleg@redhat.com> [2012-12-31 18:52:29]:
>
> >  static void handle_swbp(struct pt_regs *regs)
> >  {
> > -	struct uprobe_task *utask;
> >  	struct uprobe *uprobe;
> >  	unsigned long bp_vaddr;
> >  	int uninitialized_var(is_swbp);
> > @@ -1512,19 +1515,12 @@ static void handle_swbp(struct pt_regs *regs)
> >  	if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
> >  		goto out;
> >
> > -	utask = get_utask();
> > -	if (!utask)
> > -		goto out;	/* re-execute the instruction. */
> > -
>
> If get_utask fails with the above change, Dont we end up calling
> handler_chain twice(or more)?.

After restart, yes.

> I think this is probably true with
> previous patch too.

And this can happen with the current code too, if xol_alloc_area()
fails. So I think this is probably fine. Besides, if GFP_KERNEL
fails the task should be oom-killed in practice.

Oleg.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area()
  2012-12-31 17:52 ` [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area() Oleg Nesterov
  2013-01-08 11:55   ` Srikar Dronamraju
@ 2013-01-09 10:16   ` Anton Arapov
  2013-01-09 15:51     ` Oleg Nesterov
  1 sibling, 1 reply; 25+ messages in thread
From: Anton Arapov @ 2013-01-09 10:16 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju,
	Ananth N Mavinakayanahalli, Frank Eigler, Josh Stone,
	Suzuki K. Poulose, linux-kernel

On Mon, Dec 31, 2012 at 06:52:16PM +0100, Oleg Nesterov wrote:
> Currently only xol_get_insn_slot() does get_xol_area() + xol_alloc_area(),
> but this will have more users and we do not want to copy-and-paste this
> code. This patch simply moves xol_alloc_area() into get_xol_area() to
> simplify the current and future code.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
>  kernel/events/uprobes.c |   38 ++++++++++++++++----------------------
>  1 files changed, 16 insertions(+), 22 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 1456f7d..ef81162 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1070,27 +1070,21 @@ static int xol_add_vma(struct xol_area *area)
>  	return ret;
>  }
>  
> -static struct xol_area *get_xol_area(struct mm_struct *mm)
> -{
> -	struct xol_area *area;
> -
> -	area = mm->uprobes_state.xol_area;
> -	smp_read_barrier_depends();	/* pairs with wmb in xol_add_vma() */
> -
> -	return area;
> -}
> -
>  /*
> - * xol_alloc_area - Allocate process's xol_area.
> - * This area will be used for storing instructions for execution out of
> - * line.
> + * get_alloc_area - Allocate process's xol_area if necessary.
> + * This area will be used for storing instructions for execution out of line.
>   *
>   * Returns the allocated area or NULL.
>   */

+ * get_xol_area ....

Anton.

> -static struct xol_area *xol_alloc_area(void)
> +static struct xol_area *get_xol_area(void)
>  {
> +	struct mm_struct *mm = current->mm;
>  	struct xol_area *area;
>  
> +	area = mm->uprobes_state.xol_area;
> +	if (area)
> +		goto ret;
> +
>  	area = kzalloc(sizeof(*area), GFP_KERNEL);
>  	if (unlikely(!area))
>  		goto out;
> @@ -1113,7 +1107,10 @@ static struct xol_area *xol_alloc_area(void)
>   free_area:
>  	kfree(area);
>   out:
> -	return get_xol_area(current->mm);
> +	area = mm->uprobes_state.xol_area;
> + ret:
> +	smp_read_barrier_depends();     /* pairs with wmb in xol_add_vma() */
> +	return area;
>  }
>  
>  /*
> @@ -1189,14 +1186,11 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot
>  	unsigned long offset;
>  	void *vaddr;
>  
> -	area = get_xol_area(current->mm);
> -	if (!area) {
> -		area = xol_alloc_area();
> -		if (!area)
> -			return 0;
> -	}
> -	current->utask->xol_vaddr = xol_take_insn_slot(area);
> +	area = get_xol_area();
> +	if (!area)
> +		return 0;
>  
> +	current->utask->xol_vaddr = xol_take_insn_slot(area);
>  	/*
>  	 * Initialize the slot if xol_vaddr points to valid
>  	 * instruction slot.
> -- 
> 1.5.5.1
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix
  2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
                   ` (6 preceding siblings ...)
  2012-12-31 17:52 ` [PATCH 7/7] uprobes: Kill the bogus IS_ERR_VALUE(xol_vaddr) check Oleg Nesterov
@ 2013-01-09 10:25 ` Anton Arapov
  7 siblings, 0 replies; 25+ messages in thread
From: Anton Arapov @ 2013-01-09 10:25 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju,
	Ananth N Mavinakayanahalli, Frank Eigler, Josh Stone,
	Suzuki K. Poulose, linux-kernel

On Mon, Dec 31, 2012 at 06:51:50PM +0100, Oleg Nesterov wrote:
> Hello.
> 
> This series fixes the minor bug and cleanups the usage of add_utask()
> and xol_alloc_area(). Plus it cleanups the initializaion of ->utask
> in handle_swbp() paths.
> 
> Anton, this conflicts with your uretprobe patches, but I think we
> should do this to avoid the code duplication. IOW, I consider this
> series as a minor preparations for uretprobes as well.
> 
> Oleg.
> 
>  kernel/events/uprobes.c |  150 +++++++++++++++++++++--------------------------
>  1 files changed, 68 insertions(+), 82 deletions(-)
>

I haven't found anything other than small style problems, I've pointed
to in other mails to this thread.

And this patchset doesn't brake anything on my machine. :)

Acked-by: Anton Arapov <anton@redhat.com>

Anton.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area()
  2013-01-09 10:16   ` Anton Arapov
@ 2013-01-09 15:51     ` Oleg Nesterov
  0 siblings, 0 replies; 25+ messages in thread
From: Oleg Nesterov @ 2013-01-09 15:51 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju,
	Ananth N Mavinakayanahalli, Frank Eigler, Josh Stone,
	Suzuki K. Poulose, linux-kernel

On 01/09, Anton Arapov wrote:
>
> On Mon, Dec 31, 2012 at 06:52:16PM +0100, Oleg Nesterov wrote:
> > + * get_alloc_area - Allocate process's xol_area if necessary.
> > + * This area will be used for storing instructions for execution out of line.
> >   *
> >   * Returns the allocated area or NULL.
> >   */
>
> + * get_xol_area ....

Ah, comment, yes. Thanks, fixed.

Oleg.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area()
  2013-01-08 17:58     ` Oleg Nesterov
@ 2013-01-09 17:44       ` Srikar Dronamraju
  0 siblings, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-09 17:44 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2013-01-08 18:58:22]:

> On 01/08, Srikar Dronamraju wrote:
> >
> > (One simple check below)
> >
> > Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
> 
> Thanks,
> 
> > > @@ -1072,11 +1064,8 @@ static int xol_add_vma(struct xol_area *area)
> > >  	smp_wmb();	/* pairs with get_xol_area() */
> > >  	mm->uprobes_state.xol_area = area;
> > >  	ret = 0;
> > > -
> > > -fail:
> > > + fail:
> >
> > Not sure if the space before label is intentional?
> > Its true of other labels below also.
> 
> Yes, this was intentional although almost subconscious.
> 
> Personally I prefer to add a space before the label, this helps
> /usr/bin/diff to not confuse this label with the function name.
> 
> But I can stop this if you dislike.

I dont have any preference. Just wanted to check if it was intentional
or accidental. I thought checkpatch.pl cribs for this.
I think somebody while reviewing my patches had pointed out the same to me.
I cant remember who and probably my format wasnt just a single space
before label.

> 
> Oleg.
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout()
  2013-01-08 17:44     ` Oleg Nesterov
@ 2013-01-10 12:48       ` Srikar Dronamraju
  0 siblings, 0 replies; 25+ messages in thread
From: Srikar Dronamraju @ 2013-01-10 12:48 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, Frank Eigler, Josh Stone, Suzuki K. Poulose,
	linux-kernel

> > >  	utask->vaddr = bp_vaddr;
> > >
> > > -	return arch_uprobe_pre_xol(&uprobe->arch, regs);
> > > +	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
> > > +	if (unlikely(err)) {
> > > +		xol_free_insn_slot(current);
> > > +		return err;
> > > +	}
> > > +
> > > +	return 0;
> > >  }
> >
> > Nit: we could reduce a line or two with
> >
> > 	err = arch_uprobe_pre_xol(&uprobe->arch, regs);
> > 	if (unlikely(err))
> > 		xol_free_insn_slot(current);
> >
> > 	return err;
> 
> Yes, but this is also preparation for the next patch which adds more
> code after arch_uprobe_pre_xol() == 0.
> 

Agree

-- 
Thanks and Regards
Srikar


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2013-01-10 12:49 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-31 17:51 [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Oleg Nesterov
2012-12-31 17:52 ` [PATCH 1/7] uprobes: Move alloc_page() from xol_add_vma() to xol_alloc_area() Oleg Nesterov
2013-01-07  9:16   ` Anton Arapov
2013-01-07 16:11     ` Oleg Nesterov
2013-01-08 11:46   ` Srikar Dronamraju
2013-01-08 17:58     ` Oleg Nesterov
2013-01-09 17:44       ` Srikar Dronamraju
2012-12-31 17:52 ` [PATCH 2/7] uprobes: Fold xol_alloc_area() into get_xol_area() Oleg Nesterov
2013-01-08 11:55   ` Srikar Dronamraju
2013-01-09 10:16   ` Anton Arapov
2013-01-09 15:51     ` Oleg Nesterov
2012-12-31 17:52 ` [PATCH 3/7] uprobes: Turn add_utask() into get_utask() Oleg Nesterov
2013-01-08 11:57   ` Srikar Dronamraju
2012-12-31 17:52 ` [PATCH 4/7] uprobes: Do not play with utask in xol_get_insn_slot() Oleg Nesterov
2013-01-08 12:07   ` Srikar Dronamraju
2012-12-31 17:52 ` [PATCH 5/7] uprobes: Fix utask->xol_vaddr leak in pre_ssout() Oleg Nesterov
2013-01-08 12:13   ` Srikar Dronamraju
2013-01-08 17:44     ` Oleg Nesterov
2013-01-10 12:48       ` Srikar Dronamraju
2012-12-31 17:52 ` [PATCH 6/7] uprobes: Do not allocate current->utask unnecessary Oleg Nesterov
2013-01-08 12:20   ` Srikar Dronamraju
2013-01-08 18:13     ` Oleg Nesterov
2012-12-31 17:52 ` [PATCH 7/7] uprobes: Kill the bogus IS_ERR_VALUE(xol_vaddr) check Oleg Nesterov
2013-01-08 12:23   ` Srikar Dronamraju
2013-01-09 10:25 ` [PATCH 0/7] uprobes: alloc utask/xol_area cleanups and minor fix Anton Arapov

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).