From: Patrick Mochel Add ->k_name pointer which points to the name for a kobject. By default, this points to ->name (the static name array). Users of kobjects may use the helper function kobject_set_name() (and are encouraged to do so in all cases). This function will determined whether or not the name is short enough to fit in ->name. If so, great. Otherwise, a dyanamic string is allocated and the name is stored there. ->k_name will point to that, and will be freed when the kobject is released. kobject_set_name() may take a format string, like: kobject_set_name(kobj,"%s%d",base_name,id); and will behave as expected (will put in ->name, unless it's too long, in which case a new string will be allocated and it will be stored in there). fs/sysfs/dir.c | 8 +---- include/linux/kobject.h | 9 +++++ lib/kobject.c | 75 +++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 15 deletions(-) diff -puN fs/sysfs/dir.c~kobject-unlimited-name-lengths fs/sysfs/dir.c --- 25/fs/sysfs/dir.c~kobject-unlimited-name-lengths 2003-08-30 15:39:48.000000000 -0700 +++ 25-akpm/fs/sysfs/dir.c 2003-08-30 15:39:48.000000000 -0700 @@ -70,7 +70,7 @@ int sysfs_create_dir(struct kobject * ko else return -EFAULT; - dentry = create_dir(kobj,parent,kobj->name); + dentry = create_dir(kobj,parent,kobject_name(kobj)); if (!IS_ERR(dentry)) kobj->dentry = dentry; else @@ -157,7 +157,7 @@ void sysfs_rename_dir(struct kobject * k { struct dentry * new_dentry, * parent; - if (!strcmp(kobj->name, new_name)) + if (!strcmp(kobject_name(kobj), new_name)) return; if (!kobj->parent) @@ -169,9 +169,7 @@ void sysfs_rename_dir(struct kobject * k new_dentry = sysfs_get_dentry(parent, new_name); d_move(kobj->dentry, new_dentry); - - strlcpy(kobj->name, new_name, KOBJ_NAME_LEN); - + kobject_set_name(kobj,new_name); up(&parent->d_inode->i_sem); } diff -puN include/linux/kobject.h~kobject-unlimited-name-lengths include/linux/kobject.h --- 25/include/linux/kobject.h~kobject-unlimited-name-lengths 2003-08-30 15:39:48.000000000 -0700 +++ 25-akpm/include/linux/kobject.h 2003-08-30 15:39:48.000000000 -0700 @@ -24,6 +24,7 @@ #define KOBJ_NAME_LEN 20 struct kobject { + char * k_name; char name[KOBJ_NAME_LEN]; atomic_t refcount; struct list_head entry; @@ -33,6 +34,14 @@ struct kobject { struct dentry * dentry; }; +extern int kobject_set_name(struct kobject *, const char *, ...) + __attribute__((format(printf,2,3))); + +static inline char * kobject_name(struct kobject * kobj) +{ + return kobj->k_name; +} + extern void kobject_init(struct kobject *); extern void kobject_cleanup(struct kobject *); diff -puN lib/kobject.c~kobject-unlimited-name-lengths lib/kobject.c --- 25/lib/kobject.c~kobject-unlimited-name-lengths 2003-08-30 15:39:48.000000000 -0700 +++ 25-akpm/lib/kobject.c 2003-08-30 15:39:48.000000000 -0700 @@ -48,7 +48,7 @@ static int populate_dir(struct kobject * static int create_dir(struct kobject * kobj) { int error = 0; - if (strlen(kobj->name)) { + if (kobject_name(kobj)) { error = sysfs_create_dir(kobj); if (!error) { if ((error = populate_dir(kobj))) @@ -76,7 +76,7 @@ static int get_kobj_path_length(struct k * Add 1 to strlen for leading '/' of each level. */ do { - length += strlen (parent->name) + 1; + length += strlen(kobject_name(parent)) + 1; parent = parent->parent; } while (parent); return length; @@ -88,10 +88,10 @@ static void fill_kobj_path(struct kset * --length; for (parent = kobj; parent; parent = parent->parent) { - int cur = strlen (parent->name); + int cur = strlen(kobject_name(parent)); /* back up enough to print this name with '/' */ length -= cur; - strncpy (path + length, parent->name, cur); + strncpy (path + length, kobject_name(parent), cur); *(path + --length) = '/'; } @@ -254,11 +254,12 @@ int kobject_add(struct kobject * kobj) if (!(kobj = kobject_get(kobj))) return -ENOENT; - + if (!kobj->k_name) + kobj->k_name = kobj->name; parent = kobject_get(kobj->parent); pr_debug("kobject %s: registering. parent: %s, set: %s\n", - kobj->name, parent ? parent->name : "", + kobject_name(kobj), parent ? kobject_name(parent) : "", kobj->kset ? kobj->kset->kobj.name : "" ); if (kobj->kset) { @@ -305,7 +306,7 @@ int kobject_register(struct kobject * ko error = kobject_add(kobj); if (error) { printk("kobject_register failed for %s (%d)\n", - kobj->name,error); + kobject_name(kobj),error); dump_stack(); } } else @@ -313,6 +314,57 @@ int kobject_register(struct kobject * ko return error; } + +/** + * kobject_set_name - Set the name of an object + * @kobj: object. + * @name: name. + * + * If strlen(name) < KOBJ_NAME_LEN, then use a dynamically allocated + * string that @kobj->k_name points to. Otherwise, use the static + * @kobj->name array. + */ + +int kobject_set_name(struct kobject * kobj, const char * fmt, ...) +{ + int error = 0; + int limit = KOBJ_NAME_LEN; + int need; + va_list args; + + va_start(args,fmt); + /* + * First, try the static array + */ + need = vsnprintf(kobj->name,limit,fmt,args); + if (need < limit) + kobj->k_name = kobj->name; + else { + /* + * Need more space? Allocate it and try again + */ + kobj->k_name = kmalloc(need,GFP_KERNEL); + if (!kobj->k_name) { + error = -ENOMEM; + goto Done; + } + limit = need; + need = vsnprintf(kobj->k_name,limit,fmt,args); + + /* Still? Give up. */ + if (need > limit) { + kfree(kobj->k_name); + error = -EFAULT; + } + } + Done: + va_end(args); + return error; +} + +EXPORT_SYMBOL(kobject_set_name); + + /** * kobject_rename - change the name of an object * @kobj: object in question. @@ -360,7 +412,7 @@ void kobject_del(struct kobject * kobj) void kobject_unregister(struct kobject * kobj) { - pr_debug("kobject %s: unregistering\n",kobj->name); + pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); kobject_del(kobj); kobject_put(kobj); } @@ -392,11 +444,14 @@ void kobject_cleanup(struct kobject * ko struct kobj_type * t = get_ktype(kobj); struct kset * s = kobj->kset; - pr_debug("kobject %s: cleaning up\n",kobj->name); + pr_debug("kobject %s: cleaning up\n",kobject_name(kobj)); if (t && t->release) t->release(kobj); if (s) kset_put(s); + if (kobj->k_name != kobj->name) + kfree(kobj->k_name); + kobj->k_name = NULL; } /** @@ -488,7 +543,7 @@ struct kobject * kset_find_obj(struct ks down_read(&kset->subsys->rwsem); list_for_each(entry,&kset->list) { struct kobject * k = to_kobj(entry); - if (!strcmp(k->name,name)) { + if (!strcmp(kobject_name(k),name)) { ret = k; break; } _