memstick: avert possible race condition between idr_pre_get and idr_get_new
[firefly-linux-kernel-4.4.55.git] / drivers / memstick / core / memstick.c
index 4303b7ef73e2854a6ec9926f27214d9106c6909f..e9a3eab7b0cf407a0a9fa77cba37b96d2151bc34 100644 (file)
@@ -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);