kobject_init changes
Subsystems (5)
New thread time...
Here are two patches, one that adds a two new functions, kobject_init_ng() and kobject_init_and_add() and then a patch that shows how a number of different users are converted over to these new functions.
I choose the name "kobject_init_ng()" for now, so that I can do a patch series that converts the differnet usages in the kernel tree, and then do a global rename all at once, making it easier to find any potential problems that might happen.
Same goes for the _and_add() function, which is really just kobject_register() but without the uevent call, and it has proper memory cleanup.
Any objections to these changes?
My plans with this are:
- clean up the rest of the kernel tree usages of kobject_init()
- rename kobject_init_ng() to kobject_init().
- remove all users of kobject_register() and use the new functions and a uevent call.
- fix up the new kobject_create_and_register() function to be create_and_add() instead.
The last one will require some patch reworking in my tree, but I have four days of meetings next week, and two plane rides, so I'll need something real to do :)
I suppose if I really get bored, I can fix up the cdev stuff, but that's going to take a lot more work...
thanks,
greg k-h
RFC 1/1 kobject: add kobject_init_ng and kobject_init_and_add functions
This is what the kobject_init function is going to become. Add it to the kernel and then we can convert over the current kobject_init() users before renaming it.
Also add a kobject_init_and_add function which bundles up what a lot of the current callers want to do all at once, and it properly handles the memory usages, unlike kobject_register();
--- include/linux/kobject.h | 8 ++++ lib/kobject.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+)
include/linux/kobject.h +8 -0
@@ -79,6 +79,14 @@ static inline const char * kobject_name( }extern void kobject_init (struct kobject *); +extern int __must_check kobject_init_ng (struct kobject *kobj, +struct kobj_type *ktype, +struct kobject *parent, +const char *fmt, ...); +extern int __must_check kobject_init_and_add (struct kobject *kobj, +struct kobj_type *ktype, +struct kobject *parent, +const char *fmt, ...);extern void kobject_cleanup (struct kobject *);extern int __must_check kobject_add (struct kobject *);
lib/kobject.c +91 -0
97 lines not on this page · raw message
RFC 1/1 kobject: convert some users of kobject_init to the new functions.
This converts the kernel/ directory and the char_dev directory to use the new kobject_init functions as an example and test of them.
--- fs/char_dev.c | 18 ++++++++++++++---- kernel/module.c | 12 ++++-------- kernel/params.c | 5 +---- kernel/user.c | 5 +---- mm/slub.c | 5 +---- 5 files changed, 21 insertions(+), 24 deletions(-)
fs/char_dev.c +14 -4
@@ -509,10 +509,15 @@ static struct kobj_type ktype_cdev_dynamstruct cdev *cdev_alloc (void ) {struct cdev *p =kzalloc (sizeof (struct cdev ),GFP_KERNEL ); +int ret; +if (p) { - p->kobj.ktype = &ktype_cdev_dynamic;INIT_LIST_HEAD (&p->list); -kobject_init (&p->kobj); + ret =kobject_init_ng (&p->kobj, &ktype_cdev_dynamic,NULL , +"cdev_dynamic" ); +if (ret) +printk (KERN_ERR "cdev: something went wrong " +"initializing the dynamic kobject!\n" ); }return p; }
@@ -527,10 +532,15 @@ struct cdev *cdev_alloc(void)*/ void cdev_init (struct cdev *cdev,const struct file_operations *fops) { +int ret; +memset (cdev,0 ,sizeof *cdev);INIT_LIST_HEAD (&cdev->list); - cdev->kobj.ktype = &ktype_cdev_default; -kobject_init (&cdev->kobj); + ret =kobject_init_ng (&cdev->kobj, &ktype_cdev_default,NULL , +"cdev_static" ); +if (ret) +printk (KERN_ERR "cdev: something went very wrong initializing " +"the static kobject!\n" ); cdev->ops = fops; }
kernel/module.c +4 -8
@@ -1218,18 +1218,14 @@ int mod_sysfs_init(struct module *mod) err = -EINVAL ; goto out; } -memset (&mod->mkobj.kobj,0 ,sizeof (mod->mkobj.kobj)); - err =kobject_set_name (&mod->mkobj.kobj,"%s" , mod->name); -if (err) - goto out; - mod->mkobj.kobj.kset = module_kset; - mod->mkobj.kobj.ktype = &module_ktype; mod->mkobj.mod = mod; -kobject_init (&mod->mkobj.kobj); +memset (&mod->mkobj.kobj,0 ,sizeof (mod->mkobj.kobj)); + mod->mkobj.kobj.kset = module_kset; + err =kobject_init_and_add (&mod->mkobj.kobj, &module_ktype,NULL , +"%s" , mod->name);/* delay uevent until full sysfs population */ - err =kobject_add (&mod->mkobj.kobj); out:return err; }
kernel/params.c +1 -4
@@ -561,10 +561,7 @@ static void __init kernel_param_sysfs_se mk->mod =THIS_MODULE ; mk->kobj.kset = module_kset; - mk->kobj.ktype = &module_ktype; -kobject_set_name (&mk->kobj, name); -kobject_init (&mk->kobj); - ret =kobject_add (&mk->kobj); + ret =kobject_init_and_add (&mk->kobj, &module_ktype,NULL ,"%s" , name);if (ret) {printk (KERN_ERR "Module '%s' failed to be added to sysfs, " "error number %d\n" , name, ret);
kernel/user.c +1 -4
@@ -181,11 +181,8 @@ static int uids_user_create(struct user_int error;memset (kobj,0 ,sizeof (struct kobject )); - kobj->ktype = &uids_ktype; kobj->kset = uids_kset; -kobject_init (kobj); -kobject_set_name (&up->kobj,"%d" , up->uid); - error =kobject_add (kobj); + error =kobject_init_and_add (kobj, &uids_ktype,NULL ,"%d" , up->uid);if (error) goto done;
mm/slub.c +1 -4
@@ -4021,11 +4021,8 @@ static int sysfs_slab_add(struct kmem_ca name =create_unique_id (s); } -kobject_set_name (&s->kobj, name); s->kobj.kset = slab_kset; - s->kobj.ktype = &slab_ktype; -kobject_init (&s->kobj); - err =kobject_add (&s->kobj); + err =kobject_init_and_add (&s->kobj, &slab_ktype,NULL , name);if (err)return err;
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
In reply to Greg KHQuoted 18 lines · Greg KH
lib/kobject.c +18
-0+/** +* 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 will properly initialize a kobject and then call +* kobject_add(). +* +* If the function returns an error, the memory allocated by the kobject +* can be safely freed, no other functions need to be called. +*/ +int kobject_init_and_add (struct kobject *kobj,struct kobj_type *ktype, +struct kobject *parent,const char *fmt, ...) +{ +va_list args; +int retval;
lib/kobject.c int kobject_set_name(struct kobject *kob · line 435
Quoted 10 lines
lib/kobject.c +10
-0+ +va_start (args, fmt); + retval =kobject_init_varg (kobj, ktype, parent, fmt, args); +va_end (args); +if (retval) +return retval; + + retval =kobject_add (kobj); +if (retval) +kobject_put (kobj);
No, no!
You have recreated the problem we have been discussing during the last couple of days. If the kobject_init_varg() routine gets an error then the kobject will need to be deallocated manually. If the kobject_add() routine gets an error then the cleanup invoked by kobject_put() will do the deallocation automatically.
But the caller can't tell in which subroutine an error occurred, so it won't know what to do when kobject_init_and_add() returns an error.
The only way to resolve this problem is to have the _init routine consume no resources and never fail. That way the only possible failure mode would be if the _add routine doesn't work, in which case either a kfree() or a kobject_put() would be acceptable.
In particular, this implies that the name should be set as part of the _add() call, not as part of _init(). This is more in line with the way the code tends to use kobjects anyhow. Unless people want to name unregistered kobjects -- does this ever happen? And it if does, can these kobjects simply be replaced by krefs?
My suggestion: Have kobject_init_ng() accept a ktype pointer but not a parent or name. Instead, make kobject_add_ng() take the parent and name (possibly a kset also). Then when kobject_init_and_add() encounters an error, it shouldn't do a _put() -- the caller can either do the _put() or just do a kfree().
Alan Stern
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 33 lines · Alan Stern
Quoted 18 lines · Greg KH
lib/kobject.c +18
-0+/** +* 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 will properly initialize a kobject and then call +* kobject_add(). +* +* If the function returns an error, the memory allocated by the kobject +* can be safely freed, no other functions need to be called. +*/ +int kobject_init_and_add (struct kobject *kobj,struct kobj_type *ktype, +struct kobject *parent,const char *fmt, ...) +{ +va_list args; +int retval;lib/kobject.c int kobject_set_name(struct kobject *kob · line 435
Quoted 10 lines
lib/kobject.c +10
-0+ +va_start (args, fmt); + retval =kobject_init_varg (kobj, ktype, parent, fmt, args); +va_end (args); +if (retval) +return retval; + + retval =kobject_add (kobj); +if (retval) +kobject_put (kobj);No, no!
Quoted 8 lines
You have recreated the problem we have been discussing during the last couple of days. If the
kobject_init_varg()routine gets an error then the kobject will need to be deallocated manually. If thekobject_add()routine gets an error then the cleanup invoked bykobject_put()will do the deallocation automatically.But the caller can't tell in which subroutine an error occurred, so it won't know what to do when
kobject_init_and_add()returns an error.
Oh crap. You're totally right. I suck.
Quoted 10 lines
The only way to resolve this problem is to have the
_initroutine consume no resources and never fail. That way the only possible failure mode would be if the_addroutine doesn't work, in which case either akfree()or akobject_put()would be acceptable.In particular, this implies that the name should be set as part of the
_add()call, not as part of_init(). This is more in line with the way the code tends to use kobjects anyhow. Unless people want to name unregistered kobjects -- does this ever happen? And it if does, can these kobjects simply be replaced by krefs?
No, the only non-registered kobjects in the tree right now are never named. So this should be safe.
Quoted 5 lines
My suggestion: Have
kobject_init_ng()accept a ktype pointer but not a parent or name. Instead, makekobject_add_ng()take the parent and name (possibly a kset also). Then whenkobject_init_and_add()encounters an error, it shouldn't do a_put()-- the caller can either do the_put()or just do akfree().
Why not the parent for init()? Isn't it always known at that time? I'll dig to be sure.
Ok, second round of patches coming up...
thanks,
greg k-h
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 8 lines · Greg KH
Quoted 5 lines
My suggestion: Have
kobject_init_ng()accept a ktype pointer but not a parent or name. Instead, makekobject_add_ng()take the parent and name (possibly a kset also). Then whenkobject_init_and_add()encounters an error, it shouldn't do a_put()-- the caller can either do the_put()or just do akfree().Why not the parent for
init()? Isn't it always known at that time? I'll dig to be sure.
You are right again, to match up with the driver core methods, we don't know the parent until add() time.
thanks,
greg k-h
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
In reply to Greg KHQuoted 8 lines · Greg KH
Quoted 5 lines
My suggestion: Have
kobject_init_ng()accept a ktype pointer but not a parent or name. Instead, makekobject_add_ng()take the parent and name (possibly a kset also). Then whenkobject_init_and_add()encounters an error, it shouldn't do a_put()-- the caller can either do the_put()or just do akfree().Why not the parent for
init()? Isn't it always known at that time? I'll dig to be sure.
Specifying the parent during _add() is more logical, because a kobject doesn't actually _do_ anything to the parent until it is registered in the parent's directory. Or to put it another way, an unregistered kobject can't have a parent in any meaningful sense so there's no point specifying the parent in the _init() call.
It's really just a matter of taste.
Alan Stern
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 8 lines · Alan Stern
Quoted 6 lines · Greg KH
Quoted 5 lines
My suggestion: Have
kobject_init_ng()accept a ktype pointer but not a parent or name. Instead, makekobject_add_ng()take the parent and name (possibly a kset also). Then whenkobject_init_and_add()encounters an error, it shouldn't do a_put()-- the caller can either do the_put()or just do akfree().
Quoted 8 lines
Quoted 2 lines
Why not the parent for
init()? Isn't it always known at that time? I'll dig to be sure.Specifying the parent during
_add()is more logical, because a kobject doesn't actually _do_ anything to the parent until it is registered in the parent's directory. Or to put it another way, an unregistered kobject can't have a parent in any meaningful sense so there's no point specifying the parent in the_init()call.
Ok, how about this:
void kobject_init(struct kobject *kobj, struct ktype *ktype);
and then:
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
After we call kobject_init() we HAVE to call kobject_put() to clean up properly. So, if kobject_add() fails, we still need to clean up with kobject_put();
That means we _can_ create a:
int kobject_init_and_add(struct kobject *kobj, struct ktype *ktype, struct kobject *parent, const char *fmt, ...);
and if that fails, then again, you have to call kobject_put() to clean things up, right?
Does this look sane?
thanks,
greg k-h
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 9 lines · Greg KH
Ok, how about this:
void kobject_init(struct kobject *kobj, struct ktype *ktype);and then:
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);After we call
kobject_init()we HAVE to callkobject_put()to clean up properly. So, ifkobject_add()fails, we still need to clean up withkobject_put();
You could put that a little less strongly. After kobject_init() you SHOULD call kobject_put() to clean up properly, and after kobject_add() you MUST call kobject_del() and kobject_put().
However if kobject_add() is never called, or if it is called and it fails, then it's okay to use kfree(). It's not clear whether this distinction will matter in practice. It's probably best to document this using your stronger description.
The same sort of rule should apply to other kernel objects, like struct device. After intialization you have to do a final _put, before that you just do a kfree(). (And initialization cannot fail.)
Quoted 5 lines
That means we _can_ create a:
int kobject_init_and_add(struct kobject *kobj, struct ktype *ktype, struct kobject *parent, const char *fmt, ...);and if that fails, then again, you have to call
kobject_put()to clean things up, right?
Right. Because you know that the failure must have occurred in the _add portion.
Quoted 1 line
Does this look sane?
Yes, I think that will all work correctly.
Alan Stern
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 12 lines · Alan Stern
Quoted 9 lines · Greg KH
Ok, how about this:
void kobject_init(struct kobject *kobj, struct ktype *ktype);and then:
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);After we call
kobject_init()we HAVE to callkobject_put()to clean up properly. So, ifkobject_add()fails, we still need to clean up withkobject_put();
Quoted 8 lines
You could put that a little less strongly. After
kobject_init()you SHOULD callkobject_put()to clean up properly, and afterkobject_add()you MUST callkobject_del()andkobject_put().However if
kobject_add()is never called, or if it is called and it fails, then it's okay to usekfree(). It's not clear whether this distinction will matter in practice. It's probably best to document this using your stronger description.
No, if kobject_add() fails, kobject_put() still must be called in order to free up the name pointer, unless you are somehow guessing that the "kobject_set_name()" portion of kobject_add() somehow failed. And you can't know that, so you have to call kobject_put() in order to be safe and clean up everything.
Now why did we not do the final kobject_put() in kobject_del() as well? Doing two calls, always in order, seems a bit strange, anyone know why it's this way?
Quoted 3 lines
The same sort of rule should apply to other kernel objects, like struct device. After intialization you have to do a final
_put, before that you just do akfree(). (And initialization cannot fail.)
Yes.
Quoted 8 lines
Quoted 5 lines
That means we _can_ create a:
int kobject_init_and_add(struct kobject *kobj, struct ktype *ktype, struct kobject *parent, const char *fmt, ...);and if that fails, then again, you have to call
kobject_put()to clean things up, right?Right. Because you know that the failure must have occurred in the
_addportion.
Ok, good, I might get this right yet :)
thanks,
greg k-h
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 8 lines · Greg KH
Quoted 4 lines
However if
kobject_add()is never called, or if it is called and it fails, then it's okay to usekfree(). It's not clear whether this distinction will matter in practice. It's probably best to document this using your stronger description.No, if
kobject_add()fails,kobject_put()still must be called in order to free up the name pointer, unless you are somehow guessing that the "kobject_set_name()" portion ofkobject_add()somehow failed.
Actually I imagined that if kobject_add() failed it would back out all the changes it made -- which means it would deallocate the name string. But requiring people to call kobject_put() will do this just as well.
Quoted 7 lines
And you
can't know that, so you have to callkobject_put()in order to be safe and clean up everything.Now why did we not do the final
kobject_put()inkobject_del()as well? Doing two calls, always in order, seems a bit strange, anyone know why it's this way?
To be symmetrical with kobject_init() and kobject_add(). Besides, isn't there kobject_unregister()? Presumably it will go away along with kobject_register(), though.
Quoted 7 lines
Quoted 3 lines
You could put that a little less strongly. After
kobject_init()you SHOULD callkobject_put()to clean up properly, and afterkobject_add()you MUST callkobject_del()andkobject_put().No, in looking at the code, you only need to call
kobject_del()to clean everything up properly, ifkobject_add()succeeds. No need to callkobject_put()yet again.
Sorry, yes, that's what I meant. After a successful call to kobject_add() you must call kobject_del() to undo the _add, and then kobject_put() for the final cleanup.
Alan Stern
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
Quoted 5 lines · Alan Stern
Quoted 4 lines · Greg KH
And you
can't know that, so you have to callkobject_put()in order to be safe and clean up everything.
Quoted 7 lines
Quoted 3 lines
Now why did we not do the final
kobject_put()inkobject_del()as well? Doing two calls, always in order, seems a bit strange, anyone know why it's this way?To be symmetrical with
kobject_init()andkobject_add(). Besides, isn't therekobject_unregister()? Presumably it will go away along withkobject_register(), though.
Yes, it will go away too, once everyone gets converted.
Quoted 11 lines
Quoted 7 lines
Quoted 3 lines
You could put that a little less strongly. After
kobject_init()you SHOULD callkobject_put()to clean up properly, and afterkobject_add()you MUST callkobject_del()andkobject_put().No, in looking at the code, you only need to call
kobject_del()to clean everything up properly, ifkobject_add()succeeds. No need to callkobject_put()yet again.Sorry, yes, that's what I meant. After a successful call to
kobject_add()you must callkobject_del()to undo the_add, and thenkobject_put()for the final cleanup.
No, kobject_del() does the put for you[1]. All that is needed is a call to kobject_del().
I'll post the updated patches in a minute, they look and seem to work much better.
thanks,
greg k-h
Re: [RFC] kobject: add kobject_init_ng and kobject_init_and_add functions
In reply to Alan SternQuoted 8 lines · Alan Stern
Quoted 6 lines · Greg KH
Ok, how about this:
void kobject_init(struct kobject *kobj, struct ktype *ktype);and then:
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
Quoted 7 lines
Quoted 3 lines
After we call
kobject_init()we HAVE to callkobject_put()to clean up properly. So, ifkobject_add()fails, we still need to clean up withkobject_put();You could put that a little less strongly. After
kobject_init()you SHOULD callkobject_put()to clean up properly, and afterkobject_add()you MUST callkobject_del()andkobject_put().
No, in looking at the code, you only need to call kobject_del() to clean everything up properly, if kobject_add() succeeds. No need to call kobject_put() yet again.
Can someone else verify that this really is correct?
thanks,
greg k-h
p.s. I think it's time to start a "travel to .nz and kick a certain ex-kernel-developer around a bit" fund...