Skip to content

Commit

Permalink
kobject: remove the static array for the name
Browse files Browse the repository at this point in the history
Due to historical reasons, struct kobject contained a static array for
the name, and a dynamic pointer in case the name got bigger than the
array.  That's just dumb, as people didn't always know which variable to
reference, even with the accessor for the kobject name.

This patch removes the static array, potentially saving a lot of memory
as the majority of kobjects do not have a very long name.

Thanks to Kay for the idea to do this.

Cc: Kay Sievers <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
gregkh committed Oct 12, 2007
1 parent 34980ca commit ce2c9cb
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 44 deletions.
7 changes: 3 additions & 4 deletions include/linux/kobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ extern const char *kobject_actions[];

struct kobject {
const char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject * parent;
Expand Down Expand Up @@ -188,18 +187,18 @@ extern struct kobject * kset_find_obj(struct kset *, const char *);
* Use this when initializing an embedded kset with no other
* fields to initialize.
*/
#define set_kset_name(str) .kset = { .kobj = { .name = str } }
#define set_kset_name(str) .kset = { .kobj = { .k_name = str } }


#define decl_subsys(_name,_type,_uevent_ops) \
struct kset _name##_subsys = { \
.kobj = { .name = __stringify(_name) }, \
.kobj = { .k_name = __stringify(_name) }, \
.ktype = _type, \
.uevent_ops =_uevent_ops, \
}
#define decl_subsys_name(_varname,_name,_type,_uevent_ops) \
struct kset _varname##_subsys = { \
.kobj = { .name = __stringify(_name) }, \
.kobj = { .k_name = __stringify(_name) }, \
.ktype = _type, \
.uevent_ops =_uevent_ops, \
}
Expand Down
79 changes: 39 additions & 40 deletions lib/kobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *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);
Expand All @@ -181,7 +181,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *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);
Expand Down Expand Up @@ -255,54 +255,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.
Expand Down Expand Up @@ -477,13 +473,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);
Expand Down

0 comments on commit ce2c9cb

Please sign in to comment.