Blob Blame History Raw
From: David Herrmann <dh.herrmann@gmail.com>
Date: Sat, 18 Apr 2015 12:00:33 +0200
Subject: [PATCH] kdbus: turn kdbus_node_idr into an ida

We no longer use the node-idr for lookups. We're only interested in unique
ID allocation. Hence, turn the kdbus_node_idr into an ida and drop the now
redundant locking. This is also what kernfs does for ino allocations.

Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
 ipc/kdbus/main.c |  1 +
 ipc/kdbus/node.c | 23 +++++------------------
 ipc/kdbus/node.h |  2 ++
 3 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c
index 785f529d98b7..f8eac78cace6 100644
--- a/ipc/kdbus/main.c
+++ b/ipc/kdbus/main.c
@@ -116,6 +116,7 @@ static void __exit kdbus_exit(void)
 {
 	kdbus_fs_exit();
 	kobject_put(kdbus_dir);
+	ida_destroy(&kdbus_node_ida);
 }
 
 module_init(kdbus_init);
diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c
index 520df00e676a..0d65c65d2bde 100644
--- a/ipc/kdbus/node.c
+++ b/ipc/kdbus/node.c
@@ -178,7 +178,7 @@
  *                   accessed by other callers to properly initialize
  *                   filesystem nodes.
  *
- *     * node->id: This is an unsigned 32bit integer allocated by an IDR. It is
+ *     * node->id: This is an unsigned 32bit integer allocated by an IDA. It is
  *                 always kept as small as possible during allocation and is
  *                 globally unique across all nodes allocated by this module. 0
  *                 is reserved as "not assigned" and is the default.
@@ -233,8 +233,7 @@
 #define KDBUS_NODE_NEW			(KDBUS_NODE_BIAS - 4)
 
 /* global unique ID mapping for kdbus nodes */
-static DEFINE_IDR(kdbus_node_idr);
-static DECLARE_RWSEM(kdbus_node_idr_lock);
+DEFINE_IDA(kdbus_node_ida);
 
 /**
  * kdbus_node_name_hash() - hash a name
@@ -337,15 +336,11 @@ int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
 		node->hash = kdbus_node_name_hash(name);
 	}
 
-	down_write(&kdbus_node_idr_lock);
-	ret = idr_alloc(&kdbus_node_idr, node, 1, 0, GFP_KERNEL);
-	if (ret >= 0)
-		node->id = ret;
-	up_write(&kdbus_node_idr_lock);
-
+	ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
+	node->id = ret;
 	ret = 0;
 
 	if (parent) {
@@ -440,16 +435,8 @@ struct kdbus_node *kdbus_node_unref(struct kdbus_node *node)
 
 		if (node->free_cb)
 			node->free_cb(node);
-
-		down_write(&kdbus_node_idr_lock);
 		if (safe.id > 0)
-			idr_remove(&kdbus_node_idr, safe.id);
-		/* drop caches after last node to not leak memory on unload */
-		if (idr_is_empty(&kdbus_node_idr)) {
-			idr_destroy(&kdbus_node_idr);
-			idr_init(&kdbus_node_idr);
-		}
-		up_write(&kdbus_node_idr_lock);
+			ida_simple_remove(&kdbus_node_ida, safe.id);
 
 		kfree(safe.name);
 
diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h
index be125ce4fd58..970e02b08e9f 100644
--- a/ipc/kdbus/node.h
+++ b/ipc/kdbus/node.h
@@ -58,6 +58,8 @@ struct kdbus_node {
 
 #define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb)
 
+extern struct ida kdbus_node_ida;
+
 void kdbus_node_init(struct kdbus_node *node, unsigned int type);
 
 int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,