All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] uprobes: locking changes for filtering
@ 2012-11-24 18:02 Oleg Nesterov
  2012-11-24 18:02 ` [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem Oleg Nesterov
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Oleg Nesterov @ 2012-11-24 18:02 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, linux-kernel

Hello.

On top of
"[PATCH 0/7] uprobes: register/unregister preparations for filtering"

4/4 is not really needed and I won't insist if you dislike it.
Just this ->copy_mutex annoys me ;)

Please review. filter_chain() is almost ready, just we need to
discuss (again) its arguments/etc and reintroduce uc->filter().

Oleg.


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

* [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem
  2012-11-24 18:02 [PATCH 0/4] uprobes: locking changes for filtering Oleg Nesterov
@ 2012-11-24 18:02 ` Oleg Nesterov
  2012-12-13 14:09   ` Srikar Dronamraju
  2012-11-24 18:02 ` [PATCH 2/4] uprobes: Change filter_chain() to iterate ->consumers list Oleg Nesterov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Oleg Nesterov @ 2012-11-24 18:02 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, linux-kernel

Introduce uprobe->register_rwsem. It is taken for writing around
__uprobe_register/unregister.

Change handler_chain() to use this sem rather than consumer_rwsem.

The main reason for this change is that we have the nasty problem
with mmap_sem/consumer_rwsem dependency. filter_chain() needs to
protect uprobe->consumers like handler_chain(), but they can not
use the same lock. filter_chain() can be called under ->mmap_sem
(currently this is always true), but we want to allow ->handler()
to play with the probed task's memory, and this needs ->mmap_sem.

Alternatively we could use srcu, but synchronize_srcu() is very
slow and ->register_rwsem allows us to do more. In particular, we
can teach handler_chain() to do remove_breakpoint() if this bp is
"nacked" by all consumers, we know that we can't race with the
new consumer which does uprobe_register().

See also the next patches. uprobes_mutex[] is almost ready to die.

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

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index c80507d..03ffbb5 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -91,6 +91,7 @@ static atomic_t uprobe_events = ATOMIC_INIT(0);
 struct uprobe {
 	struct rb_node		rb_node;	/* node in the rb tree */
 	atomic_t		ref;
+	struct rw_semaphore	register_rwsem;
 	struct rw_semaphore	consumer_rwsem;
 	struct mutex		copy_mutex;	/* TODO: kill me and UPROBE_COPY_INSN */
 	struct list_head	pending_list;
@@ -449,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
 
 	uprobe->inode = igrab(inode);
 	uprobe->offset = offset;
+	init_rwsem(&uprobe->register_rwsem);
 	init_rwsem(&uprobe->consumer_rwsem);
 	mutex_init(&uprobe->copy_mutex);
 	/* For now assume that the instruction need not be single-stepped */
@@ -476,10 +478,10 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 	if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
 		return;
 
-	down_read(&uprobe->consumer_rwsem);
+	down_read(&uprobe->register_rwsem);
 	for (uc = uprobe->consumers; uc; uc = uc->next)
 		uc->handler(uc, regs);
-	up_read(&uprobe->consumer_rwsem);
+	up_read(&uprobe->register_rwsem);
 }
 
 static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc)
@@ -873,9 +875,11 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
 	mutex_lock(uprobes_hash(inode));
 	uprobe = alloc_uprobe(inode, offset);
 	if (uprobe) {
+		down_write(&uprobe->register_rwsem);
 		ret = __uprobe_register(uprobe, uc);
 		if (ret)
 			__uprobe_unregister(uprobe, uc);
+		up_write(&uprobe->register_rwsem);
 	}
 	mutex_unlock(uprobes_hash(inode));
 	if (uprobe)
@@ -899,7 +903,9 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
 		return;
 
 	mutex_lock(uprobes_hash(inode));
+	down_write(&uprobe->register_rwsem);
 	__uprobe_unregister(uprobe, uc);
+	up_write(&uprobe->register_rwsem);
 	mutex_unlock(uprobes_hash(inode));
 	put_uprobe(uprobe);
 }
-- 
1.5.5.1


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

* [PATCH 2/4] uprobes: Change filter_chain() to iterate ->consumers list
  2012-11-24 18:02 [PATCH 0/4] uprobes: locking changes for filtering Oleg Nesterov
  2012-11-24 18:02 ` [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem Oleg Nesterov
@ 2012-11-24 18:02 ` Oleg Nesterov
  2012-12-13 14:12   ` Srikar Dronamraju
  2012-11-24 18:02 ` [PATCH 3/4] uprobes: Kill UPROBE_RUN_HANDLER flag Oleg Nesterov
  2012-11-24 18:02 ` [PATCH 4/4] uprobes: Kill uprobe->copy_mutex Oleg Nesterov
  3 siblings, 1 reply; 9+ messages in thread
From: Oleg Nesterov @ 2012-11-24 18:02 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, linux-kernel

Now that it safe to use ->consumer_rwsem under ->mmap_sem we can
almost finish the implementation of filter_chain(). It still lacks
the actual uc->filter(...) call but othewrwise it is ready, just
it pretends that ->filter() always returns true.

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

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 03ffbb5..873c993 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -614,14 +614,19 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
 
 static bool filter_chain(struct uprobe *uprobe)
 {
-	/*
-	 * TODO:
-	 *	for_each_consumer(uc)
-	 *		if (uc->filter(...))
-	 *			return true;
-	 *	return false;
-	 */
-	return uprobe->consumers != NULL;
+	struct uprobe_consumer *uc;
+	bool ret = false;
+
+	down_read(&uprobe->consumer_rwsem);
+	for (uc = uprobe->consumers; uc; uc = uc->next) {
+		/* TODO: ret = uc->filter(...) */
+		ret = true;
+		if (ret)
+			break;
+	}
+	up_read(&uprobe->consumer_rwsem);
+
+	return ret;
 }
 
 static int
-- 
1.5.5.1


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

* [PATCH 3/4] uprobes: Kill UPROBE_RUN_HANDLER flag
  2012-11-24 18:02 [PATCH 0/4] uprobes: locking changes for filtering Oleg Nesterov
  2012-11-24 18:02 ` [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem Oleg Nesterov
  2012-11-24 18:02 ` [PATCH 2/4] uprobes: Change filter_chain() to iterate ->consumers list Oleg Nesterov
@ 2012-11-24 18:02 ` Oleg Nesterov
  2012-12-13 14:29   ` Srikar Dronamraju
  2012-11-24 18:02 ` [PATCH 4/4] uprobes: Kill uprobe->copy_mutex Oleg Nesterov
  3 siblings, 1 reply; 9+ messages in thread
From: Oleg Nesterov @ 2012-11-24 18:02 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, linux-kernel

Simply remove UPROBE_RUN_HANDLER and the corresponding code.

It can only help if uprobe has a single consumer, and in fact
it is no longer needed after handler_chain() was changed to use
->register_rwsem, we simply can not race with uprobe_register().

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

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 873c993..97c3874 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -83,10 +83,8 @@ static atomic_t uprobe_events = ATOMIC_INIT(0);
 
 /* Have a copy of original instruction */
 #define UPROBE_COPY_INSN	0
-/* Dont run handlers when first register/ last unregister in progress*/
-#define UPROBE_RUN_HANDLER	1
 /* Can skip singlestep */
-#define UPROBE_SKIP_SSTEP	2
+#define UPROBE_SKIP_SSTEP	1
 
 struct uprobe {
 	struct rb_node		rb_node;	/* node in the rb tree */
@@ -475,9 +473,6 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 {
 	struct uprobe_consumer *uc;
 
-	if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
-		return;
-
 	down_read(&uprobe->register_rwsem);
 	for (uc = uprobe->consumers; uc; uc = uc->next)
 		uc->handler(uc, regs);
@@ -825,13 +820,8 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
 
 static int __uprobe_register(struct uprobe *uprobe, struct uprobe_consumer *uc)
 {
-	int err;
-
 	consumer_add(uprobe, uc);
-	err = register_for_each_vma(uprobe, true);
-	if (!err) /* TODO: pointless unless the first consumer */
-		set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
-	return err;
+	return register_for_each_vma(uprobe, true);
 }
 
 static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
@@ -842,12 +832,9 @@ static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *u
 		return;
 
 	err = register_for_each_vma(uprobe, false);
-	if (!uprobe->consumers) {
-		clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
-		/* TODO : cant unregister? schedule a worker thread */
-		if (!err)
-			delete_uprobe(uprobe);
-	}
+	/* TODO : cant unregister? schedule a worker thread */
+	if (!uprobe->consumers && !err)
+		delete_uprobe(uprobe);
 }
 
 /*
-- 
1.5.5.1


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

* [PATCH 4/4] uprobes: Kill uprobe->copy_mutex
  2012-11-24 18:02 [PATCH 0/4] uprobes: locking changes for filtering Oleg Nesterov
                   ` (2 preceding siblings ...)
  2012-11-24 18:02 ` [PATCH 3/4] uprobes: Kill UPROBE_RUN_HANDLER flag Oleg Nesterov
@ 2012-11-24 18:02 ` Oleg Nesterov
  2012-12-13 14:30   ` Srikar Dronamraju
  3 siblings, 1 reply; 9+ messages in thread
From: Oleg Nesterov @ 2012-11-24 18:02 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Srikar Dronamraju
  Cc: Ananth N Mavinakayanahalli, Anton Arapov, linux-kernel

Now that ->register_rwsem is safe under ->mmap_sem we can kill
->copy_mutex and abuse down_write(&uprobe->consumer_rwsem).

This makes prepare_uprobe() even more ugly, but we should kill
it anyway.

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

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 97c3874..1e047f8 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -91,7 +91,6 @@ struct uprobe {
 	atomic_t		ref;
 	struct rw_semaphore	register_rwsem;
 	struct rw_semaphore	consumer_rwsem;
-	struct mutex		copy_mutex;	/* TODO: kill me and UPROBE_COPY_INSN */
 	struct list_head	pending_list;
 	struct uprobe_consumer	*consumers;
 	struct inode		*inode;		/* Also hold a ref to inode */
@@ -450,7 +449,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
 	uprobe->offset = offset;
 	init_rwsem(&uprobe->register_rwsem);
 	init_rwsem(&uprobe->consumer_rwsem);
-	mutex_init(&uprobe->copy_mutex);
 	/* For now assume that the instruction need not be single-stepped */
 	__set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
 
@@ -578,7 +576,8 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
 	if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
 		return ret;
 
-	mutex_lock(&uprobe->copy_mutex);
+	/* TODO: move this into _register, until then we abuse this sem. */
+	down_write(&uprobe->consumer_rwsem);
 	if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
 		goto out;
 
@@ -602,7 +601,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
 	set_bit(UPROBE_COPY_INSN, &uprobe->flags);
 
  out:
-	mutex_unlock(&uprobe->copy_mutex);
+	up_write(&uprobe->consumer_rwsem);
 
 	return ret;
 }
-- 
1.5.5.1


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

* Re: [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem
  2012-11-24 18:02 ` [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem Oleg Nesterov
@ 2012-12-13 14:09   ` Srikar Dronamraju
  0 siblings, 0 replies; 9+ messages in thread
From: Srikar Dronamraju @ 2012-12-13 14:09 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-11-24 19:02:28]:

> Introduce uprobe->register_rwsem. It is taken for writing around
> __uprobe_register/unregister.
> 
> Change handler_chain() to use this sem rather than consumer_rwsem.
> 
> The main reason for this change is that we have the nasty problem
> with mmap_sem/consumer_rwsem dependency. filter_chain() needs to
> protect uprobe->consumers like handler_chain(), but they can not
> use the same lock. filter_chain() can be called under ->mmap_sem
> (currently this is always true), but we want to allow ->handler()
> to play with the probed task's memory, and this needs ->mmap_sem.
> 
> Alternatively we could use srcu, but synchronize_srcu() is very
> slow and ->register_rwsem allows us to do more. In particular, we
> can teach handler_chain() to do remove_breakpoint() if this bp is
> "nacked" by all consumers, we know that we can't race with the
> new consumer which does uprobe_register().
> 
> See also the next patches. uprobes_mutex[] is almost ready to die.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>


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

> ---
>  kernel/events/uprobes.c |   10 ++++++++--
>  1 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index c80507d..03ffbb5 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -91,6 +91,7 @@ static atomic_t uprobe_events = ATOMIC_INIT(0);
>  struct uprobe {
>  	struct rb_node		rb_node;	/* node in the rb tree */
>  	atomic_t		ref;
> +	struct rw_semaphore	register_rwsem;
>  	struct rw_semaphore	consumer_rwsem;
>  	struct mutex		copy_mutex;	/* TODO: kill me and UPROBE_COPY_INSN */
>  	struct list_head	pending_list;
> @@ -449,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
> 
>  	uprobe->inode = igrab(inode);
>  	uprobe->offset = offset;
> +	init_rwsem(&uprobe->register_rwsem);
>  	init_rwsem(&uprobe->consumer_rwsem);
>  	mutex_init(&uprobe->copy_mutex);
>  	/* For now assume that the instruction need not be single-stepped */
> @@ -476,10 +478,10 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
>  	if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
>  		return;
> 
> -	down_read(&uprobe->consumer_rwsem);
> +	down_read(&uprobe->register_rwsem);
>  	for (uc = uprobe->consumers; uc; uc = uc->next)
>  		uc->handler(uc, regs);
> -	up_read(&uprobe->consumer_rwsem);
> +	up_read(&uprobe->register_rwsem);
>  }
> 
>  static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc)
> @@ -873,9 +875,11 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
>  	mutex_lock(uprobes_hash(inode));
>  	uprobe = alloc_uprobe(inode, offset);
>  	if (uprobe) {
> +		down_write(&uprobe->register_rwsem);
>  		ret = __uprobe_register(uprobe, uc);
>  		if (ret)
>  			__uprobe_unregister(uprobe, uc);
> +		up_write(&uprobe->register_rwsem);
>  	}
>  	mutex_unlock(uprobes_hash(inode));
>  	if (uprobe)
> @@ -899,7 +903,9 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
>  		return;
> 
>  	mutex_lock(uprobes_hash(inode));
> +	down_write(&uprobe->register_rwsem);
>  	__uprobe_unregister(uprobe, uc);
> +	up_write(&uprobe->register_rwsem);
>  	mutex_unlock(uprobes_hash(inode));
>  	put_uprobe(uprobe);
>  }
> -- 
> 1.5.5.1
> 


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

* Re: [PATCH 2/4] uprobes: Change filter_chain() to iterate ->consumers list
  2012-11-24 18:02 ` [PATCH 2/4] uprobes: Change filter_chain() to iterate ->consumers list Oleg Nesterov
@ 2012-12-13 14:12   ` Srikar Dronamraju
  0 siblings, 0 replies; 9+ messages in thread
From: Srikar Dronamraju @ 2012-12-13 14:12 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-11-24 19:02:31]:

> Now that it safe to use ->consumer_rwsem under ->mmap_sem we can
> almost finish the implementation of filter_chain(). It still lacks
> the actual uc->filter(...) call but othewrwise it is ready, just
> it pretends that ->filter() always returns true.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>


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

> ---
>  kernel/events/uprobes.c |   21 +++++++++++++--------
>  1 files changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 03ffbb5..873c993 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -614,14 +614,19 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
> 
>  static bool filter_chain(struct uprobe *uprobe)
>  {
> -	/*
> -	 * TODO:
> -	 *	for_each_consumer(uc)
> -	 *		if (uc->filter(...))
> -	 *			return true;
> -	 *	return false;
> -	 */
> -	return uprobe->consumers != NULL;
> +	struct uprobe_consumer *uc;
> +	bool ret = false;
> +
> +	down_read(&uprobe->consumer_rwsem);
> +	for (uc = uprobe->consumers; uc; uc = uc->next) {
> +		/* TODO: ret = uc->filter(...) */
> +		ret = true;
> +		if (ret)
> +			break;
> +	}
> +	up_read(&uprobe->consumer_rwsem);
> +
> +	return ret;
>  }
> 
>  static int
> -- 
> 1.5.5.1
> 


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

* Re: [PATCH 3/4] uprobes: Kill UPROBE_RUN_HANDLER flag
  2012-11-24 18:02 ` [PATCH 3/4] uprobes: Kill UPROBE_RUN_HANDLER flag Oleg Nesterov
@ 2012-12-13 14:29   ` Srikar Dronamraju
  0 siblings, 0 replies; 9+ messages in thread
From: Srikar Dronamraju @ 2012-12-13 14:29 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-11-24 19:02:33]:

> Simply remove UPROBE_RUN_HANDLER and the corresponding code.
> 
> It can only help if uprobe has a single consumer, and in fact
> it is no longer needed after handler_chain() was changed to use
> ->register_rwsem, we simply can not race with uprobe_register().
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>


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

> ---
>  kernel/events/uprobes.c |   23 +++++------------------
>  1 files changed, 5 insertions(+), 18 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 873c993..97c3874 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -83,10 +83,8 @@ static atomic_t uprobe_events = ATOMIC_INIT(0);
> 
>  /* Have a copy of original instruction */
>  #define UPROBE_COPY_INSN	0
> -/* Dont run handlers when first register/ last unregister in progress*/
> -#define UPROBE_RUN_HANDLER	1
>  /* Can skip singlestep */
> -#define UPROBE_SKIP_SSTEP	2
> +#define UPROBE_SKIP_SSTEP	1
> 
>  struct uprobe {
>  	struct rb_node		rb_node;	/* node in the rb tree */
> @@ -475,9 +473,6 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
>  {
>  	struct uprobe_consumer *uc;
> 
> -	if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
> -		return;
> -
>  	down_read(&uprobe->register_rwsem);
>  	for (uc = uprobe->consumers; uc; uc = uc->next)
>  		uc->handler(uc, regs);
> @@ -825,13 +820,8 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
> 
>  static int __uprobe_register(struct uprobe *uprobe, struct uprobe_consumer *uc)
>  {
> -	int err;
> -
>  	consumer_add(uprobe, uc);
> -	err = register_for_each_vma(uprobe, true);
> -	if (!err) /* TODO: pointless unless the first consumer */
> -		set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
> -	return err;
> +	return register_for_each_vma(uprobe, true);
>  }
> 
>  static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
> @@ -842,12 +832,9 @@ static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *u
>  		return;
> 
>  	err = register_for_each_vma(uprobe, false);
> -	if (!uprobe->consumers) {
> -		clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
> -		/* TODO : cant unregister? schedule a worker thread */
> -		if (!err)
> -			delete_uprobe(uprobe);
> -	}
> +	/* TODO : cant unregister? schedule a worker thread */
> +	if (!uprobe->consumers && !err)
> +		delete_uprobe(uprobe);
>  }
> 
>  /*
> -- 
> 1.5.5.1
> 


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

* Re: [PATCH 4/4] uprobes: Kill uprobe->copy_mutex
  2012-11-24 18:02 ` [PATCH 4/4] uprobes: Kill uprobe->copy_mutex Oleg Nesterov
@ 2012-12-13 14:30   ` Srikar Dronamraju
  0 siblings, 0 replies; 9+ messages in thread
From: Srikar Dronamraju @ 2012-12-13 14:30 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Peter Zijlstra, Ananth N Mavinakayanahalli,
	Anton Arapov, linux-kernel

* Oleg Nesterov <oleg@redhat.com> [2012-11-24 19:02:36]:

> Now that ->register_rwsem is safe under ->mmap_sem we can kill
> ->copy_mutex and abuse down_write(&uprobe->consumer_rwsem).
> 
> This makes prepare_uprobe() even more ugly, but we should kill
> it anyway.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>


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

> ---
>  kernel/events/uprobes.c |    7 +++----
>  1 files changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 97c3874..1e047f8 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -91,7 +91,6 @@ struct uprobe {
>  	atomic_t		ref;
>  	struct rw_semaphore	register_rwsem;
>  	struct rw_semaphore	consumer_rwsem;
> -	struct mutex		copy_mutex;	/* TODO: kill me and UPROBE_COPY_INSN */
>  	struct list_head	pending_list;
>  	struct uprobe_consumer	*consumers;
>  	struct inode		*inode;		/* Also hold a ref to inode */
> @@ -450,7 +449,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
>  	uprobe->offset = offset;
>  	init_rwsem(&uprobe->register_rwsem);
>  	init_rwsem(&uprobe->consumer_rwsem);
> -	mutex_init(&uprobe->copy_mutex);
>  	/* For now assume that the instruction need not be single-stepped */
>  	__set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
> 
> @@ -578,7 +576,8 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
>  	if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
>  		return ret;
> 
> -	mutex_lock(&uprobe->copy_mutex);
> +	/* TODO: move this into _register, until then we abuse this sem. */
> +	down_write(&uprobe->consumer_rwsem);
>  	if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
>  		goto out;
> 
> @@ -602,7 +601,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
>  	set_bit(UPROBE_COPY_INSN, &uprobe->flags);
> 
>   out:
> -	mutex_unlock(&uprobe->copy_mutex);
> +	up_write(&uprobe->consumer_rwsem);
> 
>  	return ret;
>  }
> -- 
> 1.5.5.1
> 


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

end of thread, other threads:[~2012-12-13 15:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-24 18:02 [PATCH 0/4] uprobes: locking changes for filtering Oleg Nesterov
2012-11-24 18:02 ` [PATCH 1/4] uprobes: Introduce uprobe->register_rwsem Oleg Nesterov
2012-12-13 14:09   ` Srikar Dronamraju
2012-11-24 18:02 ` [PATCH 2/4] uprobes: Change filter_chain() to iterate ->consumers list Oleg Nesterov
2012-12-13 14:12   ` Srikar Dronamraju
2012-11-24 18:02 ` [PATCH 3/4] uprobes: Kill UPROBE_RUN_HANDLER flag Oleg Nesterov
2012-12-13 14:29   ` Srikar Dronamraju
2012-11-24 18:02 ` [PATCH 4/4] uprobes: Kill uprobe->copy_mutex Oleg Nesterov
2012-12-13 14:30   ` Srikar Dronamraju

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.