kernel/kdbus-turn-kdbus_node_idr-i...

102 lines
3.2 KiB
Diff

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,