[PATCH 2/5] idr: use call_once()

Akinobu Mita
2008-03-10T15:08:34Z

idr_layer_cache is created when idr_init() is called first time by someone.

This patch makes the idr_layer_cache initialization to use call_once().

This conversion prevents an unlikely race condition when two idr_init()
callers attempt to create idr_layer_cache simultaneously.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
---
lib/idr.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

Index: 2.6-rc/lib/idr.c
===================================================================
--- 2.6-rc.orig/lib/idr.c
+++ 2.6-rc/lib/idr.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/once.h>
#endif
#include <linux/err.h>
#include <linux/string.h>
@@ -585,12 +586,12 @@ static void idr_cache_ctor(struct kmem_c
memset(idr_layer, 0, sizeof(struct idr_layer));
}

-static int init_id_cache(void)
+static int init_id_cache(void)
{
- if (!idr_layer_cache)
- idr_layer_cache = kmem_cache_create("idr_layer_cache",
+ idr_layer_cache = kmem_cache_create("idr_layer_cache",
sizeof(struct idr_layer), 0, 0, idr_cache_ctor);
- return 0;
+
+ return !idr_layer_cache ? -ENOMEM : 0;
}

/**
@@ -602,7 +603,9 @@ static int init_id_cache(void)
*/
void idr_init(struct idr *idp)
{
- init_id_cache();
+ static DEFINE_ONCE(once);
+
+ call_once(&once, init_id_cache);
memset(idp, 0, sizeof(struct idr));
spin_lock_init(&idp->lock);
}