]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - lib/kobject.c
kobject: clean up debugging messages
[linux-2.6-omap-h63xx.git] / lib / kobject.c
index 329fd1126b3f116ed6e0dd6d62ba2c82ebc6cfc1..1015f74212d088b471561fb1b78a4fa3aa8895f7 100644 (file)
@@ -95,7 +95,8 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length)
                *(path + --length) = '/';
        }
 
-       pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
+       pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
+                kobj, __FUNCTION__,path);
 }
 
 /**
@@ -133,7 +134,6 @@ void kobject_init(struct kobject * kobj)
                return;
        kref_init(&kobj->kref);
        INIT_LIST_HEAD(&kobj->entry);
-       kobj->kset = kset_get(kobj->kset);
 }
 
 
@@ -172,24 +172,34 @@ int kobject_add(struct kobject * kobj)
        if (!kobj->k_name)
                kobject_set_name(kobj, "NO_NAME");
        if (!*kobj->k_name) {
-               pr_debug("kobject attempted to be registered with no name!\n");
+               pr_debug("kobject (%p) attempted to be registered with no "
+                        "name!\n", kobj);
                WARN_ON(1);
                kobject_put(kobj);
                return -EINVAL;
        }
        parent = kobject_get(kobj->parent);
 
-       pr_debug("kobject %s: registering. parent: %s, set: %s\n",
-                kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", 
+       pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
+                kobject_name(kobj), kobj, __FUNCTION__,
+                parent ? kobject_name(parent) : "<NULL>",
                 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
 
        if (kobj->kset) {
-               spin_lock(&kobj->kset->list_lock);
+               kobj->kset = kset_get(kobj->kset);
 
-               if (!parent)
+               if (!parent) {
                        parent = kobject_get(&kobj->kset->kobj);
+                       /*
+                        * If the kset is our parent, get a second
+                        * reference, we drop both the kset and the
+                        * parent ref on cleanup
+                        */
+                       kobject_get(parent);
+               }
 
-               list_add_tail(&kobj->entry,&kobj->kset->list);
+               spin_lock(&kobj->kset->list_lock);
+               list_add_tail(&kobj->entry, &kobj->kset->list);
                spin_unlock(&kobj->kset->list_lock);
                kobj->parent = parent;
        }
@@ -390,6 +400,33 @@ int kobject_add_ng(struct kobject *kobj, struct kobject *parent,
 }
 EXPORT_SYMBOL(kobject_add_ng);
 
+/**
+ * kobject_init_and_add - initialize a kobject structure and add it to the kobject hierarchy
+ * @kobj: pointer to the kobject to initialize
+ * @ktype: pointer to the ktype for this kobject.
+ * @parent: pointer to the parent of this kobject.
+ * @fmt: the name of the kobject.
+ *
+ * This function combines the call to kobject_init_ng() and
+ * kobject_add_ng().  The same type of error handling after a call to
+ * kobject_add_ng() and kobject lifetime rules are the same here.
+ */
+int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
+                        struct kobject *parent, const char *fmt, ...)
+{
+       va_list args;
+       int retval;
+
+       kobject_init_ng(kobj, ktype);
+
+       va_start(args, fmt);
+       retval = kobject_add_varg(kobj, parent, fmt, args);
+       va_end(args);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(kobject_init_and_add);
+
 /**
  *     kobject_rename - change the name of an object
  *     @kobj:  object in question.
@@ -526,7 +563,8 @@ void kobject_unregister(struct kobject * kobj)
 {
        if (!kobj)
                return;
-       pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
+       pr_debug("kobject: '%s' (%p): %s\n",
+                kobject_name(kobj), kobj, __FUNCTION__);
        kobject_uevent(kobj, KOBJ_REMOVE);
        kobject_del(kobj);
        kobject_put(kobj);
@@ -555,7 +593,8 @@ static void kobject_cleanup(struct kobject *kobj)
        struct kobject * parent = kobj->parent;
        const char *name = kobj->k_name;
 
-       pr_debug("kobject %s: cleaning up\n",kobject_name(kobj));
+       pr_debug("kobject: '%s' (%p): %s\n",
+                kobject_name(kobj), kobj, __FUNCTION__);
        if (t && t->release) {
                t->release(kobj);
                /* If we have a release function, we can guess that this was
@@ -585,65 +624,73 @@ void kobject_put(struct kobject * kobj)
                kref_put(&kobj->kref, kobject_release);
 }
 
-
-static void dir_release(struct kobject *kobj)
+static void dynamic_kobj_release(struct kobject *kobj)
 {
+       pr_debug("kobject: '%s' (%p): %s\n",
+                kobject_name(kobj), kobj, __FUNCTION__);
        kfree(kobj);
 }
 
-static struct kobj_type dir_ktype = {
-       .release        = dir_release,
-       .sysfs_ops      = NULL,
-       .default_attrs  = NULL,
+static struct kobj_type dynamic_kobj_ktype = {
+       .release        = dynamic_kobj_release,
+       .sysfs_ops      = &kobj_sysfs_ops,
 };
 
 /**
- *     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.
+ * kobject_create - create a struct kobject dynamically
+ *
+ * This function creates a kobject structure dynamically and sets it up
+ * to be a "dynamic" kobject with a default release function set up.
  *
- *     Add a plain directory object as child of given object.
+ * If the kobject was not able to be created, NULL will be returned.
+ * The kobject structure returned from here must be cleaned up with a
+ * call to kobject_put() and not kfree(), as kobject_init_ng() has
+ * already been called on this structure.
  */
-struct kobject *kobject_kset_add_dir(struct kset *kset,
-                                    struct kobject *parent, const char *name)
+struct kobject *kobject_create(void)
 {
-       struct kobject *k;
-       int ret;
-
-       if (!parent)
-               return NULL;
-
-       k = kzalloc(sizeof(*k), GFP_KERNEL);
-       if (!k)
-               return NULL;
+       struct kobject *kobj;
 
-       k->kset = kset;
-       k->parent = parent;
-       k->ktype = &dir_ktype;
-       kobject_set_name(k, name);
-       ret = kobject_register(k);
-       if (ret < 0) {
-               printk(KERN_WARNING "%s: kobject_register error: %d\n",
-                       __func__, ret);
-               kobject_del(k);
+       kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
+       if (!kobj)
                return NULL;
-       }
 
-       return k;
+       kobject_init_ng(kobj, &dynamic_kobj_ktype);
+       return kobj;
 }
 
 /**
- *     kobject_add_dir - add sub directory of object.
- *     @parent:        object in which a directory is created.
- *     @name:  directory name.
+ * kobject_create_and_add - create a struct kobject dynamically and register it with sysfs
  *
- *     Add a plain directory object as child of given object.
+ * @name: the name for the kset
+ * @parent: the parent kobject of this kobject, if any.
+ *
+ * This function creates a kset structure dynamically and registers it
+ * with sysfs.  When you are finished with this structure, call
+ * kobject_unregister() and the structure will be dynamically freed when
+ * it is no longer being used.
+ *
+ * If the kobject was not able to be created, NULL will be returned.
  */
-struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
+struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
 {
-       return kobject_kset_add_dir(NULL, parent, name);
+       struct kobject *kobj;
+       int retval;
+
+       kobj = kobject_create();
+       if (!kobj)
+               return NULL;
+
+       retval = kobject_add_ng(kobj, parent, "%s", name);
+       if (retval) {
+               printk(KERN_WARNING "%s: kobject_add error: %d\n",
+                      __FUNCTION__, retval);
+               kobject_put(kobj);
+               kobj = NULL;
+       }
+       return kobj;
 }
+EXPORT_SYMBOL_GPL(kobject_create_and_add);
 
 /**
  *     kset_init - initialize a kset for use
@@ -657,6 +704,35 @@ void kset_init(struct kset * k)
        spin_lock_init(&k->list_lock);
 }
 
+/* default kobject attribute operations */
+static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,
+                             char *buf)
+{
+       struct kobj_attribute *kattr;
+       ssize_t ret = -EIO;
+
+       kattr = container_of(attr, struct kobj_attribute, attr);
+       if (kattr->show)
+               ret = kattr->show(kobj, kattr, buf);
+       return ret;
+}
+
+static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
+                              const char *buf, size_t count)
+{
+       struct kobj_attribute *kattr;
+       ssize_t ret = -EIO;
+
+       kattr = container_of(attr, struct kobj_attribute, attr);
+       if (kattr->store)
+               ret = kattr->store(kobj, kattr, buf, count);
+       return ret;
+}
+
+struct sysfs_ops kobj_sysfs_ops = {
+       .show   = kobj_attr_show,
+       .store  = kobj_attr_store,
+};
 
 /**
  *     kset_add - add a kset object to the hierarchy.
@@ -730,35 +806,90 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
        return ret;
 }
 
-int subsystem_register(struct kset *s)
+static void kset_release(struct kobject *kobj)
 {
-       return kset_register(s);
+       struct kset *kset = container_of(kobj, struct kset, kobj);
+       pr_debug("kobject: '%s' (%p): %s\n",
+                kobject_name(kobj), kobj, __FUNCTION__);
+       kfree(kset);
 }
 
-void subsystem_unregister(struct kset *s)
+static struct kobj_type kset_ktype = {
+       .sysfs_ops      = &kobj_sysfs_ops,
+       .release = kset_release,
+};
+
+/**
+ * kset_create - create a struct kset dynamically
+ *
+ * @name: the name for the kset
+ * @uevent_ops: a struct kset_uevent_ops for the kset
+ * @parent_kobj: the parent kobject of this kset, if any.
+ *
+ * This function creates a kset structure dynamically.  This structure can
+ * then be registered with the system and show up in sysfs with a call to
+ * kset_register().  When you are finished with this structure, if
+ * kset_register() has been called, call kset_unregister() and the
+ * structure will be dynamically freed when it is no longer being used.
+ *
+ * If the kset was not able to be created, NULL will be returned.
+ */
+static struct kset *kset_create(const char *name,
+                               struct kset_uevent_ops *uevent_ops,
+                               struct kobject *parent_kobj)
 {
-       kset_unregister(s);
+       struct kset *kset;
+
+       kset = kzalloc(sizeof(*kset), GFP_KERNEL);
+       if (!kset)
+               return NULL;
+       kobject_set_name(&kset->kobj, name);
+       kset->uevent_ops = uevent_ops;
+       kset->kobj.parent = parent_kobj;
+
+       /*
+        * The kobject of this kset will have a type of kset_ktype and belong to
+        * no kset itself.  That way we can properly free it when it is
+        * finished being used.
+        */
+       kset->kobj.ktype = &kset_ktype;
+       kset->kobj.kset = NULL;
+
+       return kset;
 }
 
 /**
- *     subsystem_create_file - export sysfs attribute file.
- *     @s:     subsystem.
- *     @a:     subsystem attribute descriptor.
+ * kset_create_and_add - create a struct kset dynamically and add it to sysfs
+ *
+ * @name: the name for the kset
+ * @uevent_ops: a struct kset_uevent_ops for the kset
+ * @parent_kobj: the parent kobject of this kset, if any.
+ *
+ * This function creates a kset structure dynamically and registers it
+ * with sysfs.  When you are finished with this structure, call
+ * kset_unregister() and the structure will be dynamically freed when it
+ * is no longer being used.
+ *
+ * If the kset was not able to be created, NULL will be returned.
  */
-
-int subsys_create_file(struct kset *s, struct subsys_attribute *a)
+struct kset *kset_create_and_add(const char *name,
+                                struct kset_uevent_ops *uevent_ops,
+                                struct kobject *parent_kobj)
 {
-       int error = 0;
-
-       if (!s || !a)
-               return -EINVAL;
+       struct kset *kset;
+       int error;
 
-       if (kset_get(s)) {
-               error = sysfs_create_file(&s->kobj, &a->attr);
-               kset_put(s);
+       kset = kset_create(name, uevent_ops, parent_kobj);
+       if (!kset)
+               return NULL;
+       error = kset_register(kset);
+       if (error) {
+               kfree(kset);
+               return NULL;
        }
-       return error;
+       return kset;
 }
+EXPORT_SYMBOL_GPL(kset_create_and_add);
 
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
@@ -770,7 +901,3 @@ EXPORT_SYMBOL(kobject_del);
 
 EXPORT_SYMBOL(kset_register);
 EXPORT_SYMBOL(kset_unregister);
-
-EXPORT_SYMBOL(subsystem_register);
-EXPORT_SYMBOL(subsystem_unregister);
-EXPORT_SYMBOL(subsys_create_file);