From 25ffd0cde0fe4f04c14d59e7b5d9958fd09662ba Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Thu, 24 Apr 2014 21:45:10 -0400
Subject: [PATCH 233/414] idr: Use local lock instead of preempt enable/disable

We need to protect the per cpu variable and prevent migration.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/idr.h |  4 ++++
 lib/idr.c           | 37 ++++++++++++++++++++++++++++++++++---
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/include/linux/idr.h b/include/linux/idr.h
index 871a213a8477..267527b0f7d3 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -92,10 +92,14 @@ void idr_init(struct idr *idp);
  * Each idr_preload() should be matched with an invocation of this
  * function.  See idr_preload() for details.
  */
+#ifdef CONFIG_PREEMPT_RT_FULL
+void idr_preload_end(void);
+#else
 static inline void idr_preload_end(void)
 {
 	preempt_enable();
 }
+#endif
 
 /**
  * idr_find - return pointer for given id
diff --git a/lib/idr.c b/lib/idr.c
index 674c30bc2ed0..c9a8dbcafcbc 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -37,6 +37,7 @@
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/locallock.h>
 
 #define MAX_IDR_SHIFT		(sizeof(int) * 8 - 1)
 #define MAX_IDR_BIT		(1U << MAX_IDR_SHIFT)
@@ -389,6 +390,36 @@ int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 }
 EXPORT_SYMBOL(__idr_get_new_above);
 
+#ifdef CONFIG_PREEMPT_RT_FULL
+static DEFINE_LOCAL_IRQ_LOCK(idr_lock);
+
+static inline void idr_preload_lock(void)
+{
+	local_lock(idr_lock);
+}
+
+static inline void idr_preload_unlock(void)
+{
+	local_unlock(idr_lock);
+}
+
+void idr_preload_end(void)
+{
+	idr_preload_unlock();
+}
+EXPORT_SYMBOL(idr_preload_end);
+#else
+static inline void idr_preload_lock(void)
+{
+	preempt_disable();
+}
+
+static inline void idr_preload_unlock(void)
+{
+	preempt_enable();
+}
+#endif
+
 /**
  * idr_preload - preload for idr_alloc()
  * @gfp_mask: allocation mask to use for preloading
@@ -423,7 +454,7 @@ void idr_preload(gfp_t gfp_mask)
 	WARN_ON_ONCE(in_interrupt());
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
-	preempt_disable();
+	idr_preload_lock();
 
 	/*
 	 * idr_alloc() is likely to succeed w/o full idr_layer buffer and
@@ -435,9 +466,9 @@ void idr_preload(gfp_t gfp_mask)
 	while (__this_cpu_read(idr_preload_cnt) < MAX_IDR_FREE) {
 		struct idr_layer *new;
 
-		preempt_enable();
+		idr_preload_unlock();
 		new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
-		preempt_disable();
+		idr_preload_lock();
 		if (!new)
 			break;
 
-- 
2.10.2

