]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/base/core.c
driver-core: fix race condition in get_device_parent()
[net-next-2.6.git] / drivers / base / core.c
index 282025770429b08f329373c1a286637c6a210f45..fb4bc4f5151cad6c1c017354708cd798e08140a9 100644 (file)
@@ -607,6 +607,7 @@ static struct kobject *get_device_parent(struct device *dev,
        int retval;
 
        if (dev->class) {
+               static DEFINE_MUTEX(gdp_mutex);
                struct kobject *kobj = NULL;
                struct kobject *parent_kobj;
                struct kobject *k;
@@ -623,6 +624,8 @@ static struct kobject *get_device_parent(struct device *dev,
                else
                        parent_kobj = &parent->kobj;
 
+               mutex_lock(&gdp_mutex);
+
                /* find our class-directory at the parent and reference it */
                spin_lock(&dev->class->p->class_dirs.list_lock);
                list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
@@ -631,20 +634,26 @@ static struct kobject *get_device_parent(struct device *dev,
                                break;
                        }
                spin_unlock(&dev->class->p->class_dirs.list_lock);
-               if (kobj)
+               if (kobj) {
+                       mutex_unlock(&gdp_mutex);
                        return kobj;
+               }
 
                /* or create a new class-directory at the parent device */
                k = kobject_create();
-               if (!k)
+               if (!k) {
+                       mutex_unlock(&gdp_mutex);
                        return NULL;
+               }
                k->kset = &dev->class->p->class_dirs;
                retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
                if (retval < 0) {
+                       mutex_unlock(&gdp_mutex);
                        kobject_put(k);
                        return NULL;
                }
                /* do not emit an uevent for this simple "glue" directory */
+               mutex_unlock(&gdp_mutex);
                return k;
        }