diff options
author | Alex Dubov <oakad@yahoo.com> | 2011-01-12 20:01:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 11:03:22 -0500 |
commit | d8256d487840f9c2c372f8fc615a5d378bc133f1 (patch) | |
tree | c9b17bcf583e047ecb55bf775b55053c85b21935 | |
parent | 8930c8aa740b12ad69f44a35137bcc39bfa3dc41 (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>
-rw-r--r-- | drivers/memstick/core/memstick.c | 18 | ||||
-rw-r--r-- | drivers/memstick/core/mspro_block.c | 6 |
2 files changed, 15 insertions, 9 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) | |||
511 | { | 511 | { |
512 | int rc; | 512 | int rc; |
513 | 513 | ||
514 | if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL)) | 514 | while (1) { |
515 | return -ENOMEM; | 515 | if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL)) |
516 | return -ENOMEM; | ||
516 | 517 | ||
517 | spin_lock(&memstick_host_lock); | 518 | spin_lock(&memstick_host_lock); |
518 | rc = idr_get_new(&memstick_host_idr, host, &host->id); | 519 | rc = idr_get_new(&memstick_host_idr, host, &host->id); |
519 | spin_unlock(&memstick_host_lock); | 520 | spin_unlock(&memstick_host_lock); |
520 | if (rc) | 521 | if (!rc) |
521 | return rc; | 522 | break; |
523 | else if (rc != -EAGAIN) | ||
524 | return rc; | ||
525 | } | ||
522 | 526 | ||
523 | dev_set_name(&host->dev, "memstick%u", host->id); | 527 | dev_set_name(&host->dev, "memstick%u", host->id); |
524 | 528 | ||
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 02362eccc58..a167938d451 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -1206,10 +1206,12 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
1206 | 1206 | ||
1207 | msb->page_size = be16_to_cpu(sys_info->unit_size); | 1207 | msb->page_size = be16_to_cpu(sys_info->unit_size); |
1208 | 1208 | ||
1209 | if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) | 1209 | mutex_lock(&mspro_block_disk_lock); |
1210 | if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) { | ||
1211 | mutex_unlock(&mspro_block_disk_lock); | ||
1210 | return -ENOMEM; | 1212 | return -ENOMEM; |
1213 | } | ||
1211 | 1214 | ||
1212 | mutex_lock(&mspro_block_disk_lock); | ||
1213 | rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); | 1215 | rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); |
1214 | mutex_unlock(&mspro_block_disk_lock); | 1216 | mutex_unlock(&mspro_block_disk_lock); |
1215 | 1217 | ||