#include <linux/stat.h>
#include <linux/slab.h>
-/**
- * populate_dir - populate directory with attributes.
- * @kobj: object we're working on.
- *
- * Most subsystems have a set of default attributes that
- * are associated with an object that registers with them.
- * This is a helper called during object registration that
- * loops through the default attributes of the subsystem
- * and creates attributes files for them in sysfs.
+/*
+ * populate_dir - populate directory with attributes.
+ * @kobj: object we're working on.
*
+ * Most subsystems have a set of default attributes that are associated
+ * with an object that registers with them. This is a helper called during
+ * object registration that loops through the default attributes of the
+ * subsystem and creates attributes files for them in sysfs.
*/
-
-static int populate_dir(struct kobject * kobj)
+static int populate_dir(struct kobject *kobj)
{
- struct kobj_type * t = get_ktype(kobj);
- struct attribute * attr;
+ struct kobj_type *t = get_ktype(kobj);
+ struct attribute *attr;
int error = 0;
int i;
-
+
if (t && t->default_attrs) {
for (i = 0; (attr = t->default_attrs[i]) != NULL; i++) {
- if ((error = sysfs_create_file(kobj,attr)))
+ error = sysfs_create_file(kobj, attr);
+ if (error)
break;
}
}
return error;
}
-static int create_dir(struct kobject * kobj)
+static int create_dir(struct kobject *kobj)
{
int error = 0;
if (kobject_name(kobj)) {
error = sysfs_create_dir(kobj);
if (!error) {
- if ((error = populate_dir(kobj)))
+ error = populate_dir(kobj);
+ if (error)
sysfs_remove_dir(kobj);
}
}
return error;
}
-static inline struct kobject * to_kobj(struct list_head * entry)
-{
- return container_of(entry,struct kobject,entry);
-}
-
static int get_kobj_path_length(struct kobject *kobj)
{
int length = 1;
- struct kobject * parent = kobj;
+ struct kobject *parent = kobj;
- /* walk up the ancestors until we hit the one pointing to the
+ /* walk up the ancestors until we hit the one pointing to the
* root.
* Add 1 to strlen for leading '/' of each level.
*/
static void fill_kobj_path(struct kobject *kobj, char *path, int length)
{
- struct kobject * parent;
+ struct kobject *parent;
--length;
for (parent = kobj; parent; parent = parent->parent) {
int cur = strlen(kobject_name(parent));
/* back up enough to print this name with '/' */
length -= cur;
- strncpy (path + length, kobject_name(parent), cur);
+ strncpy(path + length, kobject_name(parent), cur);
*(path + --length) = '/';
}
pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
- kobj, __FUNCTION__,path);
+ kobj, __func__, path);
}
/**
kset_put(kobj->kset);
}
-static void kobject_init_internal(struct kobject * kobj)
+static void kobject_init_internal(struct kobject *kobj)
{
if (!kobj)
return;
kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry);
+ kobj->state_in_sysfs = 0;
+ kobj->state_add_uevent_sent = 0;
+ kobj->state_remove_uevent_sent = 0;
+ kobj->state_initialized = 1;
}
static int kobject_add_internal(struct kobject *kobj)
{
int error = 0;
- struct kobject * parent;
+ struct kobject *parent;
if (!kobj)
return -ENOENT;
- if (!kobj->k_name || !kobj->k_name[0]) {
- pr_debug("kobject: (%p): attempted to be registered with empty "
+ if (!kobj->name || !kobj->name[0]) {
+ WARN(1, "kobject: (%p): attempted to be registered with empty "
"name!\n", kobj);
- WARN_ON(1);
return -EINVAL;
}
}
pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
- kobject_name(kobj), kobj, __FUNCTION__,
+ kobject_name(kobj), kobj, __func__,
parent ? kobject_name(parent) : "<NULL>",
- kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
+ kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
error = create_dir(kobj);
if (error) {
printk(KERN_ERR "%s failed for %s with "
"-EEXIST, don't try to register things with "
"the same name in the same directory.\n",
- __FUNCTION__, kobject_name(kobj));
+ __func__, kobject_name(kobj));
else
printk(KERN_ERR "%s failed for %s (%d)\n",
- __FUNCTION__, kobject_name(kobj), error);
+ __func__, kobject_name(kobj), error);
dump_stack();
} else
kobj->state_in_sysfs = 1;
* @fmt: format string used to build the name
* @vargs: vargs to format the string.
*/
-static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
+int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
va_list vargs)
{
- va_list aq;
- char *name;
+ const char *old_name = kobj->name;
+ char *s;
- va_copy(aq, vargs);
- name = kvasprintf(GFP_KERNEL, fmt, vargs);
- va_end(aq);
+ if (kobj->name && !fmt)
+ return 0;
- if (!name)
+ kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
+ if (!kobj->name)
return -ENOMEM;
+ /* ewww... some of these buggers have '/' in the name ... */
+ while ((s = strchr(kobj->name, '/')))
+ s[0] = '!';
- /* Free the old name, if necessary. */
- kfree(kobj->k_name);
-
- /* Now, set the new name */
- kobj->k_name = name;
- kobj->state_name_set = 1;
-
+ kfree(old_name);
return 0;
}
*/
int kobject_set_name(struct kobject *kobj, const char *fmt, ...)
{
- va_list args;
+ va_list vargs;
int retval;
- va_start(args, fmt);
- retval = kobject_set_name_vargs(kobj, fmt, args);
- va_end(args);
+ va_start(vargs, fmt);
+ retval = kobject_set_name_vargs(kobj, fmt, vargs);
+ va_end(vargs);
return retval;
}
dump_stack();
}
- kref_init(&kobj->kref);
- INIT_LIST_HEAD(&kobj->entry);
+ kobject_init_internal(kobj);
kobj->ktype = ktype;
- kobj->state_name_set = 0;
- kobj->state_in_sysfs = 0;
- kobj->state_add_uevent_sent = 0;
- kobj->state_remove_uevent_sent = 0;
- kobj->state_initialized = 1;
return;
error:
static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
const char *fmt, va_list vargs)
{
- va_list aq;
int retval;
- va_copy(aq, vargs);
- retval = kobject_set_name_vargs(kobj, fmt, aq);
- va_end(aq);
+ retval = kobject_set_name_vargs(kobj, fmt, vargs);
if (retval) {
printk(KERN_ERR "kobject: can not set name properly!\n");
return retval;
EXPORT_SYMBOL_GPL(kobject_init_and_add);
/**
- * kobject_rename - change the name of an object
- * @kobj: object in question.
- * @new_name: object's new name
+ * kobject_rename - change the name of an object
+ * @kobj: object in question.
+ * @new_name: object's new name
+ *
+ * It is the responsibility of the caller to provide mutual
+ * exclusion between two different calls of kobject_rename
+ * on the same kobject and to ensure that new_name is valid and
+ * won't conflict with other kobjects.
*/
-
-int kobject_rename(struct kobject * kobj, const char *new_name)
+int kobject_rename(struct kobject *kobj, const char *new_name)
{
int error = 0;
const char *devpath = NULL;
+ const char *dup_name = NULL, *name;
char *devpath_string = NULL;
char *envp[2];
if (!kobj->parent)
return -EINVAL;
- /* see if this name is already in use */
- if (kobj->kset) {
- struct kobject *temp_kobj;
- temp_kobj = kset_find_obj(kobj->kset, new_name);
- if (temp_kobj) {
- printk(KERN_WARNING "kobject '%s' cannot be renamed "
- "to '%s' as '%s' is already in existence.\n",
- kobject_name(kobj), new_name, new_name);
- kobject_put(temp_kobj);
- return -EINVAL;
- }
- }
-
devpath = kobject_get_path(kobj, GFP_KERNEL);
if (!devpath) {
error = -ENOMEM;
envp[0] = devpath_string;
envp[1] = NULL;
+ name = dup_name = kstrdup(new_name, GFP_KERNEL);
+ if (!name) {
+ error = -ENOMEM;
+ goto out;
+ }
+
error = sysfs_rename_dir(kobj, new_name);
+ if (error)
+ goto out;
+
+ /* Install the new kobject name */
+ dup_name = kobj->name;
+ kobj->name = name;
/* This function is mostly/only used for network interface.
* Some hotplug package track interfaces by their name and
* therefore want to know when the name is changed by the user. */
- if (!error)
- kobject_uevent_env(kobj, KOBJ_MOVE, envp);
+ kobject_uevent_env(kobj, KOBJ_MOVE, envp);
out:
+ kfree(dup_name);
kfree(devpath_string);
kfree(devpath);
kobject_put(kobj);
return error;
}
+EXPORT_SYMBOL_GPL(kobject_rename);
/**
- * kobject_move - move object to another parent
- * @kobj: object in question.
- * @new_parent: object's new parent (can be NULL)
+ * kobject_move - move object to another parent
+ * @kobj: object in question.
+ * @new_parent: object's new parent (can be NULL)
*/
-
int kobject_move(struct kobject *kobj, struct kobject *new_parent)
{
int error;
}
/**
- * kobject_del - unlink kobject from hierarchy.
- * @kobj: object.
+ * kobject_del - unlink kobject from hierarchy.
+ * @kobj: object.
*/
-
-void kobject_del(struct kobject * kobj)
+void kobject_del(struct kobject *kobj)
{
if (!kobj)
return;
}
/**
- * kobject_unregister - remove object from hierarchy and decrement refcount.
- * @kobj: object going away.
- */
-
-void kobject_unregister(struct kobject * kobj)
-{
- if (!kobj)
- return;
- pr_debug("kobject: '%s' (%p): %s\n",
- kobject_name(kobj), kobj, __FUNCTION__);
- kobject_uevent(kobj, KOBJ_REMOVE);
- kobject_del(kobj);
- kobject_put(kobj);
-}
-
-/**
- * kobject_get - increment refcount for object.
- * @kobj: object.
+ * kobject_get - increment refcount for object.
+ * @kobj: object.
*/
-
-struct kobject * kobject_get(struct kobject * kobj)
+struct kobject *kobject_get(struct kobject *kobj)
{
if (kobj)
kref_get(&kobj->kref);
static void kobject_cleanup(struct kobject *kobj)
{
struct kobj_type *t = get_ktype(kobj);
- const char *name = kobj->k_name;
- int name_set = kobj->state_name_set;
+ const char *name = kobj->name;
pr_debug("kobject: '%s' (%p): %s\n",
- kobject_name(kobj), kobj, __FUNCTION__);
+ kobject_name(kobj), kobj, __func__);
if (t && !t->release)
pr_debug("kobject: '%s' (%p): does not have a release() "
}
/* free name if we allocated it */
- if (name_set && name) {
+ if (name) {
pr_debug("kobject: '%s': free name\n", name);
kfree(name);
}
}
/**
- * kobject_put - decrement refcount for object.
- * @kobj: object.
+ * kobject_put - decrement refcount for object.
+ * @kobj: object.
*
- * Decrement the refcount, and if 0, call kobject_cleanup().
+ * Decrement the refcount, and if 0, call kobject_cleanup().
*/
-void kobject_put(struct kobject * kobj)
+void kobject_put(struct kobject *kobj)
{
- if (kobj)
+ if (kobj) {
+ if (!kobj->state_initialized)
+ WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
+ "initialized, yet kobject_put() is being "
+ "called.\n", kobject_name(kobj), kobj);
kref_put(&kobj->kref, kobject_release);
+ }
}
static void dynamic_kobj_release(struct kobject *kobj)
{
- pr_debug("kobject: (%p): %s\n", kobj, __FUNCTION__);
+ pr_debug("kobject: (%p): %s\n", kobj, __func__);
kfree(kobj);
}
* @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
+ * This function creates a kobject 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
+ * kobject_put() 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.
retval = kobject_add(kobj, parent, "%s", name);
if (retval) {
printk(KERN_WARNING "%s: kobject_add error: %d\n",
- __FUNCTION__, retval);
+ __func__, retval);
kobject_put(kobj);
kobj = NULL;
}
EXPORT_SYMBOL_GPL(kobject_create_and_add);
/**
- * kset_init - initialize a kset for use
- * @k: kset
+ * kset_init - initialize a kset for use
+ * @k: kset
*/
-
-void kset_init(struct kset * k)
+void kset_init(struct kset *k)
{
kobject_init_internal(&k->kobj);
INIT_LIST_HEAD(&k->list);
};
/**
- * kset_register - initialize and add a kset.
- * @k: kset.
+ * kset_register - initialize and add a kset.
+ * @k: kset.
*/
-
-int kset_register(struct kset * k)
+int kset_register(struct kset *k)
{
int err;
return 0;
}
-
/**
- * kset_unregister - remove a kset.
- * @k: kset.
+ * kset_unregister - remove a kset.
+ * @k: kset.
*/
-
-void kset_unregister(struct kset * k)
+void kset_unregister(struct kset *k)
{
if (!k)
return;
- kobject_unregister(&k->kobj);
+ kobject_put(&k->kobj);
}
-
/**
- * kset_find_obj - search for object in kset.
- * @kset: kset we're looking in.
- * @name: object's name.
+ * kset_find_obj - search for object in kset.
+ * @kset: kset we're looking in.
+ * @name: object's name.
*
- * Lock kset via @kset->subsys, and iterate over @kset->list,
- * looking for a matching kobject. If matching object is found
- * take a reference and return the object.
+ * Lock kset via @kset->subsys, and iterate over @kset->list,
+ * looking for a matching kobject. If matching object is found
+ * take a reference and return the object.
*/
-
-struct kobject * kset_find_obj(struct kset * kset, const char * name)
+struct kobject *kset_find_obj(struct kset *kset, const char *name)
{
- struct list_head * entry;
- struct kobject * ret = NULL;
+ struct kobject *k;
+ struct kobject *ret = NULL;
spin_lock(&kset->list_lock);
- list_for_each(entry,&kset->list) {
- struct kobject * k = to_kobj(entry);
- if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
+ list_for_each_entry(k, &kset->list, entry) {
+ if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
ret = kobject_get(k);
break;
}
{
struct kset *kset = container_of(kobj, struct kset, kobj);
pr_debug("kobject: '%s' (%p): %s\n",
- kobject_name(kobj), kobj, __FUNCTION__);
+ kobject_name(kobj), kobj, __func__);
kfree(kset);
}
struct kobject *parent_kobj)
{
struct kset *kset;
+ int retval;
kset = kzalloc(sizeof(*kset), GFP_KERNEL);
if (!kset)
return NULL;
- kobject_set_name(&kset->kobj, name);
+ retval = kobject_set_name(&kset->kobj, name);
+ if (retval) {
+ kfree(kset);
+ return NULL;
+ }
kset->uevent_ops = uevent_ops;
kset->kobj.parent = parent_kobj;
}
EXPORT_SYMBOL_GPL(kset_create_and_add);
-EXPORT_SYMBOL(kobject_unregister);
EXPORT_SYMBOL(kobject_get);
EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL(kobject_del);