From: David Herrmann 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 Signed-off-by: David Herrmann Acked-by: Daniel Mack --- 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,