Merge branch 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block
[safe/jmp/linux-2.6] / lib / kobject.c
index eb251aa..03d4036 100644 (file)
@@ -2,6 +2,8 @@
  * kobject.c - library routines for handling generic kernel objects
  *
  * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
+ * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (c) 2006-2007 Novell Inc.
  *
  * This file is released under the GPLv2.
  *
@@ -44,11 +46,11 @@ static int populate_dir(struct kobject * kobj)
        return error;
 }
 
-static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+static int create_dir(struct kobject * kobj)
 {
        int error = 0;
        if (kobject_name(kobj)) {
-               error = sysfs_create_dir(kobj, shadow_parent);
+               error = sysfs_create_dir(kobj);
                if (!error) {
                        if ((error = populate_dir(kobj)))
                                sysfs_remove_dir(kobj);
@@ -131,7 +133,6 @@ void kobject_init(struct kobject * kobj)
                return;
        kref_init(&kobj->kref);
        INIT_LIST_HEAD(&kobj->entry);
-       init_waitqueue_head(&kobj->poll);
        kobj->kset = kset_get(kobj->kset);
 }
 
@@ -157,12 +158,11 @@ static void unlink(struct kobject * kobj)
 }
 
 /**
- *     kobject_shadow_add - add an object to the hierarchy.
+ *     kobject_add - add an object to the hierarchy.
  *     @kobj:  object.
- *     @shadow_parent: sysfs directory to add to.
  */
 
-int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
+int kobject_add(struct kobject * kobj)
 {
        int error = 0;
        struct kobject * parent;
@@ -170,7 +170,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
        if (!(kobj = kobject_get(kobj)))
                return -ENOENT;
        if (!kobj->k_name)
-               kobj->k_name = kobj->name;
+               kobject_set_name(kobj, "NO_NAME");
        if (!*kobj->k_name) {
                pr_debug("kobject attempted to be registered with no name!\n");
                WARN_ON(1);
@@ -181,7 +181,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
 
        pr_debug("kobject %s: registering. parent: %s, set: %s\n",
                 kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", 
-                kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
+                kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
 
        if (kobj->kset) {
                spin_lock(&kobj->kset->list_lock);
@@ -194,7 +194,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
                kobj->parent = parent;
        }
 
-       error = create_dir(kobj, shadow_parent);
+       error = create_dir(kobj);
        if (error) {
                /* unlink does the kobject_put() for us */
                unlink(kobj);
@@ -202,30 +202,20 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
 
                /* be noisy on error issues */
                if (error == -EEXIST)
-                       printk("kobject_add failed for %s with -EEXIST, "
-                              "don't try to register things with the "
-                              "same name in the same directory.\n",
+                       printk(KERN_ERR "kobject_add failed for %s with "
+                              "-EEXIST, don't try to register things with "
+                              "the same name in the same directory.\n",
                               kobject_name(kobj));
                else
-                       printk("kobject_add failed for %s (%d)\n",
+                       printk(KERN_ERR "kobject_add failed for %s (%d)\n",
                               kobject_name(kobj), error);
-                dump_stack();
+               dump_stack();
        }
 
        return error;
 }
 
 /**
- *     kobject_add - add an object to the hierarchy.
- *     @kobj:  object.
- */
-int kobject_add(struct kobject * kobj)
-{
-       return kobject_shadow_add(kobj, NULL);
-}
-
-
-/**
  *     kobject_register - initialize and add an object.
  *     @kobj:  object in question.
  */
@@ -255,54 +245,50 @@ int kobject_register(struct kobject * kobj)
 int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
 {
        int error = 0;
-       int limit = KOBJ_NAME_LEN;
+       int limit;
        int need;
        va_list args;
-       char * name;
+       char *name;
 
-       /* 
-        * First, try the static array 
-        */
-       va_start(args,fmt);
-       need = vsnprintf(kobj->name,limit,fmt,args);
+       /* find out how big a buffer we need */
+       name = kmalloc(1024, GFP_KERNEL);
+       if (!name) {
+               error = -ENOMEM;
+               goto done;
+       }
+       va_start(args, fmt);
+       need = vsnprintf(name, 1024, fmt, args);
        va_end(args);
-       if (need < limit) 
-               name = kobj->name;
-       else {
-               /* 
-                * Need more space? Allocate it and try again 
-                */
-               limit = need + 1;
-               name = kmalloc(limit,GFP_KERNEL);
-               if (!name) {
-                       error = -ENOMEM;
-                       goto Done;
-               }
-               va_start(args,fmt);
-               need = vsnprintf(name,limit,fmt,args);
-               va_end(args);
-
-               /* Still? Give up. */
-               if (need >= limit) {
-                       kfree(name);
-                       error = -EFAULT;
-                       goto Done;
-               }
+       kfree(name);
+
+       /* Allocate the new space and copy the string in */
+       limit = need + 1;
+       name = kmalloc(limit, GFP_KERNEL);
+       if (!name) {
+               error = -ENOMEM;
+               goto done;
+       }
+       va_start(args, fmt);
+       need = vsnprintf(name, limit, fmt, args);
+       va_end(args);
+
+       /* something wrong with the string we copied? */
+       if (need >= limit) {
+               kfree(name);
+               error = -EFAULT;
+               goto done;
        }
 
        /* Free the old name, if necessary. */
-       if (kobj->k_name && kobj->k_name != kobj->name)
-               kfree(kobj->k_name);
+       kfree(kobj->k_name);
 
        /* Now, set the new name */
        kobj->k_name = name;
- Done:
+done:
        return error;
 }
-
 EXPORT_SYMBOL(kobject_set_name);
 
-
 /**
  *     kobject_rename - change the name of an object
  *     @kobj:  object in question.
@@ -338,7 +324,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
        /* Note : if we want to send the new name alone, not the full path,
         * we could probably use kobject_name(kobj); */
 
-       error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
+       error = sysfs_rename_dir(kobj, new_name);
 
        /* This function is mostly/only used for network interface.
         * Some hotplug package track interfaces by their name and
@@ -355,27 +341,6 @@ out:
 }
 
 /**
- *     kobject_rename - change the name of an object
- *     @kobj:  object in question.
- *     @new_parent: object's new parent
- *     @new_name: object's new name
- */
-
-int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
-                         const char *new_name)
-{
-       int error = 0;
-
-       kobj = kobject_get(kobj);
-       if (!kobj)
-               return -EINVAL;
-       error = sysfs_rename_dir(kobj, new_parent, new_name);
-       kobject_put(kobj);
-
-       return error;
-}
-
-/**
  *     kobject_move - move object to another parent
  *     @kobj:  object in question.
  *     @new_parent: object's new parent (can be NULL)
@@ -477,13 +442,16 @@ void kobject_cleanup(struct kobject * kobj)
        struct kobj_type * t = get_ktype(kobj);
        struct kset * s = kobj->kset;
        struct kobject * parent = kobj->parent;
+       const char *name = kobj->k_name;
 
        pr_debug("kobject %s: cleaning up\n",kobject_name(kobj));
-       if (kobj->k_name != kobj->name)
-               kfree(kobj->k_name);
-       kobj->k_name = NULL;
-       if (t && t->release)
+       if (t && t->release) {
                t->release(kobj);
+               /* If we have a release function, we can guess that this was
+                * not a statically allocated kobject, so we should be safe to
+                * free the name */
+               kfree(name);
+       }
        if (s)
                kset_put(s);
        kobject_put(parent);
@@ -519,7 +487,7 @@ static struct kobj_type dir_ktype = {
 };
 
 /**
- *     kobject__kset_add_dir - add sub directory of object.
+ *     kobject_kset_add_dir - add sub directory of object.
  *     @kset:          kset the directory is belongs to.
  *     @parent:        object in which a directory is created.
  *     @name:  directory name.
@@ -545,8 +513,8 @@ struct kobject *kobject_kset_add_dir(struct kset *kset,
        kobject_set_name(k, name);
        ret = kobject_register(k);
        if (ret < 0) {
-               printk(KERN_WARNING "kobject_add_dir: "
-                       "kobject_register error: %d\n", ret);
+               printk(KERN_WARNING "%s: kobject_register error: %d\n",
+                       __func__, ret);
                kobject_del(k);
                return NULL;
        }
@@ -554,6 +522,13 @@ struct kobject *kobject_kset_add_dir(struct kset *kset,
        return k;
 }
 
+/**
+ *     kobject_add_dir - add sub directory of object.
+ *     @parent:        object in which a directory is created.
+ *     @name:  directory name.
+ *
+ *     Add a plain directory object as child of given object.
+ */
 struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
 {
        return kobject_kset_add_dir(NULL, parent, name);
@@ -575,22 +550,10 @@ void kset_init(struct kset * k)
 /**
  *     kset_add - add a kset object to the hierarchy.
  *     @k:     kset.
- *
- *     Simply, this adds the kset's embedded kobject to the 
- *     hierarchy. 
- *     We also try to make sure that the kset's embedded kobject
- *     has a parent before it is added. We only care if the embedded
- *     kobject is not part of a kset itself, since kobject_add()
- *     assigns a parent in that case. 
- *     If that is the case, and the kset has a controlling subsystem,
- *     then we set the kset's parent to be said subsystem. 
  */
 
 int kset_add(struct kset * k)
 {
-       if (!k->kobj.parent && !k->kobj.kset && k->subsys)
-               k->kobj.parent = &k->subsys->kset.kobj;
-
        return kobject_add(&k->kobj);
 }
 
@@ -602,10 +565,17 @@ int kset_add(struct kset * k)
 
 int kset_register(struct kset * k)
 {
+       int err;
+
        if (!k)
                return -EINVAL;
+
        kset_init(k);
-       return kset_add(k);
+       err = kset_add(k);
+       if (err)
+               return err;
+       kobject_uevent(&k->kobj, KOBJ_ADD);
+       return 0;
 }
 
 
@@ -649,84 +619,36 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
        return ret;
 }
 
-
-void subsystem_init(struct subsystem * s)
-{
-       init_rwsem(&s->rwsem);
-       kset_init(&s->kset);
-}
-
-/**
- *     subsystem_register - register a subsystem.
- *     @s:     the subsystem we're registering.
- *
- *     Once we register the subsystem, we want to make sure that 
- *     the kset points back to this subsystem for correct usage of 
- *     the rwsem. 
- */
-
-int subsystem_register(struct subsystem * s)
+int subsystem_register(struct kset *s)
 {
-       int error;
-
-       if (!s)
-               return -EINVAL;
-
-       subsystem_init(s);
-       pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
-
-       if (!(error = kset_add(&s->kset))) {
-               if (!s->kset.subsys)
-                       s->kset.subsys = s;
-       }
-       return error;
+       return kset_register(s);
 }
 
-void subsystem_unregister(struct subsystem * s)
+void subsystem_unregister(struct kset *s)
 {
-       if (!s)
-               return;
-       pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
-       kset_unregister(&s->kset);
+       kset_unregister(s);
 }
 
-
 /**
  *     subsystem_create_file - export sysfs attribute file.
  *     @s:     subsystem.
  *     @a:     subsystem attribute descriptor.
  */
 
-int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
+int subsys_create_file(struct kset *s, struct subsys_attribute *a)
 {
        int error = 0;
 
        if (!s || !a)
                return -EINVAL;
 
-       if (subsys_get(s)) {
-               error = sysfs_create_file(&s->kset.kobj,&a->attr);
-               subsys_put(s);
+       if (kset_get(s)) {
+               error = sysfs_create_file(&s->kobj, &a->attr);
+               kset_put(s);
        }
        return error;
 }
 
-
-/**
- *     subsystem_remove_file - remove sysfs attribute file.
- *     @s:     subsystem.
- *     @a:     attribute desciptor.
- */
-#if 0
-void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
-{
-       if (subsys_get(s)) {
-               sysfs_remove_file(&s->kset.kobj,&a->attr);
-               subsys_put(s);
-       }
-}
-#endif  /*  0  */
-
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
 EXPORT_SYMBOL(kobject_unregister);