diff mbox series

genirq: add mutex and rcu locking to irq_desc_tree

Message ID 1509416928-7450-1-git-send-email-yamada.masahiro@socionext.com
State New
Headers show
Series genirq: add mutex and rcu locking to irq_desc_tree | expand

Commit Message

Masahiro Yamada Oct. 31, 2017, 2:28 a.m. UTC
Add a mutex to prevent concurrency on the updater side of the
irq_desc radix tree.

Add rcu_read_lock/unlock to the reader side so that lifetimes of
leaf pointers of the radix tree are correctly managed.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>

---

 kernel/irq/irqdesc.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

-- 
2.7.4

Comments

Thomas Gleixner Oct. 31, 2017, 10:29 p.m. UTC | #1
On Tue, 31 Oct 2017, Masahiro Yamada wrote:

> Add a mutex to prevent concurrency on the updater side of the

> irq_desc radix tree.


The callers of insert/delete are already serialized by sparse_irq_lock. SO
why would we need yet another mutex?

> Add rcu_read_lock/unlock to the reader side so that lifetimes of

> leaf pointers of the radix tree are correctly managed.


That rcu protection is only needed for callers which have special life time
requirements and they have that already. For the bulk of the callers rcu
read lock is not required unless I'm missing something.

Thanks,

	tglx
diff mbox series

Patch

diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 82afb7e..928c896 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -12,6 +12,7 @@ 
 #include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 #include <linux/bitmap.h>
 #include <linux/irqdomain.h>
@@ -312,21 +313,32 @@  static void irq_sysfs_add(int irq, struct irq_desc *desc) {}
 #endif /* CONFIG_SYSFS */
 
 static RADIX_TREE(irq_desc_tree, GFP_KERNEL);
+static DEFINE_MUTEX(irq_desc_tree_mutex);
 
 static void irq_insert_desc(unsigned int irq, struct irq_desc *desc)
 {
+	mutex_lock(&irq_desc_tree_mutex);
 	radix_tree_insert(&irq_desc_tree, irq, desc);
+	mutex_unlock(&irq_desc_tree_mutex);
 }
 
 struct irq_desc *irq_to_desc(unsigned int irq)
 {
-	return radix_tree_lookup(&irq_desc_tree, irq);
+	struct irq_desc *desc;
+
+	rcu_read_lock();
+	desc = radix_tree_lookup(&irq_desc_tree, irq);
+	rcu_read_unlock();
+
+	return desc;
 }
 EXPORT_SYMBOL(irq_to_desc);
 
 static void delete_irq_desc(unsigned int irq)
 {
+	mutex_lock(&irq_desc_tree_mutex);
 	radix_tree_delete(&irq_desc_tree, irq);
+	mutex_unlock(&irq_desc_tree_mutex);
 }
 
 #ifdef CONFIG_SMP