aboutsummaryrefslogtreecommitdiff
path: root/drivers/memstick/core/memstick.c
diff options
context:
space:
mode:
authorAlex Dubov <oakad@yahoo.com>2011-01-12 17:01:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 08:03:22 -0800
commitd8256d487840f9c2c372f8fc615a5d378bc133f1 (patch)
treec9b17bcf583e047ecb55bf775b55053c85b21935 /drivers/memstick/core/memstick.c
parent8930c8aa740b12ad69f44a35137bcc39bfa3dc41 (diff)
memstick: avert possible race condition between idr_pre_get and idr_get_new
Implement the usual pattern around idr_pre_get() and idr_get_new() to handlethe situation where another thread concurrently steals this thread's idr_pre_get() preallocation. Signed-off-by: Alex Dubov <oakad@yahoo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/memstick/core/memstick.c')
-rw-r--r--drivers/memstick/core/memstick.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index 4303b7ef73e..e9a3eab7b0c 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -511,14 +511,18 @@ int memstick_add_host(struct memstick_host *host)
{
int rc;
- if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))
- return -ENOMEM;
+ while (1) {
+ if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))
+ return -ENOMEM;
- spin_lock(&memstick_host_lock);
- rc = idr_get_new(&memstick_host_idr, host, &host->id);
- spin_unlock(&memstick_host_lock);
- if (rc)
- return rc;
+ spin_lock(&memstick_host_lock);
+ rc = idr_get_new(&memstick_host_idr, host, &host->id);
+ spin_unlock(&memstick_host_lock);
+ if (!rc)
+ break;
+ else if (rc != -EAGAIN)
+ return rc;
+ }
dev_set_name(&host->dev, "memstick%u", host->id);