[tip:perf/core] uprobes: _unregister() should always do register_for_each_vma(false)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit-ID:  04aab9b2006bbdeff78dc162f206fdfebeca97d9
Gitweb:     http://git.kernel.org/tip/04aab9b2006bbdeff78dc162f206fdfebeca97d9
Author:     Oleg Nesterov <oleg@xxxxxxxxxx>
AuthorDate: Fri, 23 Nov 2012 19:43:50 +0100
Committer:  Oleg Nesterov <oleg@xxxxxxxxxx>
CommitDate: Fri, 8 Feb 2013 17:47:03 +0100

uprobes: _unregister() should always do register_for_each_vma(false)

uprobe_unregister() removes the breakpoints only if the last consumer
goes away. To support the filtering it should do this every time, we
want to remove the breakpoints which nobody else want to keep.

Note: given that filter_chain() is not actually implemented, this patch
itself doesn't change the behaviour yet, register_for_each_vma(false)
is a heavy "nop" unless there are no more consumers.

Signed-off-by: Oleg Nesterov <oleg@xxxxxxxxxx>
Acked-by: Srikar Dronamraju <srikar@xxxxxxxxxxxxxxxxxx>
---
 kernel/events/uprobes.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index c38bf37..9401990 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -825,12 +825,20 @@ static int __uprobe_register(struct uprobe *uprobe)
 	return register_for_each_vma(uprobe, true);
 }
 
-static void __uprobe_unregister(struct uprobe *uprobe)
+static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
 {
-	if (!register_for_each_vma(uprobe, false))
-		delete_uprobe(uprobe);
+	int err;
+
+	if (!consumer_del(uprobe, uc))	/* WARN? */
+		return;
 
-	/* TODO : cant unregister? schedule a worker thread */
+	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);
+	}
 }
 
 /*
@@ -868,8 +876,7 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
 	} else if (!consumer_add(uprobe, uc)) {
 		ret = __uprobe_register(uprobe);
 		if (ret) {
-			uprobe->consumers = NULL;
-			__uprobe_unregister(uprobe);
+			__uprobe_unregister(uprobe, uc);
 		} else {
 			set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
 		}
@@ -897,14 +904,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
 		return;
 
 	mutex_lock(uprobes_hash(inode));
-
-	if (consumer_del(uprobe, uc)) {
-		if (!uprobe->consumers) {
-			__uprobe_unregister(uprobe);
-			clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
-		}
-	}
-
+	__uprobe_unregister(uprobe, uc);
 	mutex_unlock(uprobes_hash(inode));
 	put_uprobe(uprobe);
 }
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux