Re: [RFC] kobject/kset/ktype documentation and example code updated

From: Randy Dunlap
Date: Thu Dec 20 2007 - 01:33:28 EST


On Wed, 19 Dec 2007 16:30:31 -0800 Greg KH wrote:

> Everything you never wanted to know about kobjects, ksets, and ktypes
>
> Greg Kroah-Hartman <gregkh@xxxxxxx>
>
> Based on an original article by Jon Corbet for lwn.net written October 1,
> 2003 and located at http://lwn.net/Articles/51437/
>
> Last updated December 19, 2007
>
>
...
> - A ktype is the type of object that embeds a kobject. Every structure
> that embeds a kobject needs a corresponding ktype. The ktype controls
> what happens when a kobject is no longer referenced and the kobject's
> default representation in sysfs.

I can't quite parse the last sentence above. Is it:

The ktype controls (a) what happens ...
and (b) the kobject's default representation in sysfs.

?

> Embedding kobjects
>
> So, for example, the UIO code has a structure that defines the memory
> region associated with a uio device:
>
> struct uio_mem {
> struct kobject kobj;
> unsigned long addr;
> unsigned long size;
> int memtype;
> void __iomem *internal_addr;
> };
>
> If you have a struct uio_mem structure, finding its embedded kobject is
> just a matter of using the kobj structure. Code that works with kobjects
> will often have the opposite problem, however: given a struct kobject
> pointer, what is the pointer to the containing structure? You must avoid
> tricks (such as assuming that the kobject is at the beginning of the
> structure) and, instead, use the container_of() macro, found in
> <linux/kernel.h>:
>
> container_of(pointer, type, member)
>
> where pointer is the pointer to the embedded kobject, type is the type of
> the containing structure, and member is the name of the structure field to
> which pointer points. The return value from container_of() is a pointer to
> the given type. So, for example, a pointer to a struct kobject embedded

This is (still) confusing to me. Is it:
a pointer "kp" to a ...
or is struct uio_mem the "kp"?

> within a struct uio_mem called "kp" could be converted to a pointer to the
> containing structure with:
>
> struct uio_mem *u_mem = container_of(kp, struct uio_mem, kobj);
>
> Programmers will often define a simple macro for "back-casting" kobject

Drop the "will".

> pointers to the containing type.
>
>
> Initialization of kobjects
>
>
> int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
>
> This sets up the parent of the kobject, and the name for the kobject

Drop the comma.

> properly. If the kobject is to be associated with a specific kset, that
> assignment must be done before calling kobject_add(). If a kset is
> associated with a kobject, then the parent for the kobject can be set to
> NULL in the call to kobject_add() and then the kobject will be placed under
> the kset itself.
>
> As the name of the kobject is set when it is added to the kernel, the name
> of the kobject should never be manipulated directly. If you must change
> the name of the kobject, call kobject_rename():
>
> int kobject_rename(struct kobject *kobj, const char *new_name);
>
> There is a function called kobject_set_name() but that is legacy cruft and
> is being removed. If your code needs to call this function, it is
> incorrect and needs to be fixed.

Is kobject_set_name() marked as __deprecated ?

> Uevents
>
> After a kobject has been registered with the kobject core, it needs to be
> announced to the world that it has been created. This can be done with
> call to kobject_uevent():

a call ...

>
> int kobject_uevent(struct kobject *kobj, enum kobject_action action);
>
> Use the KOBJ_ADD action for when the kobject is first added to the kernel.
> This should be done only after any attributes or children of the kobject
> have been initialized properly, as userspace will instantly start to look

s/will/may/

> for them when this call happens.
>
> When the kobject is removed from the kernel (details on how to do that is

are

> below), the uevent for KOBJ_REMOVE will be automatically created by the
> kobject core, so the caller does not have to worry about doing that by
> hand.
>
>
> Reference counts
>
...
>
> Because kobjects are dynamic, they must not be declared statically or on
> the stack, but instead, always allocated from the heap. Future versions of

The kernel has heapspace?

> the kernel will contain a run-time check for kobjects that are created
> statically and will warn the developer of this improper usage.
>
> If all that you are wanting to use a kobject for is to provide a reference

If all that you want to use a kobject for is to provide a reference

> counter for your structure, please use the struct kref instead, a kobject
> would be overkill. For more information on how to use struct kref, please
> see the file, Documentation/kref.txt in the Linux kernel source tree.

Drop comma.

>
>
> Creating "simple" kobjects
>
> Sometimes all that a developer wants is a way to create a simple directory
> in the sysfs hierarchy, and not have to mess with the whole complication of
> ksets, show and store functions, and other details. This is the one
> exception where a single kobject should be created. To create such an
> entry, use the function:
>
> struct kobject *kobject_create_and_add(char *name, struct kobject *parent);
>
> This function will create a kobject and place it in sysfs in the location
> underneath the specified parent kobject. To create simple attributes
> associated with this kobject, use:
>
> int sysfs_create_file(struct kobject *kobj, struct attribute *attr);
> or
> int sysfs_create_group(struct kobject *kobj, struct attribute_group *grp);
>
> Both types of attributes used here, with a kobject that has been created
> with the kobject_create_and_add() can be of type kobj_attribute, no special
> custom attribute is needed to be created.

^ multi-run-on sentences....

> See the example module, samples/kobject/kobject-example.c for an
> implementation of a simple kobject and attributes.
>
>
>
> ktypes and release methods
>
...
> The end result is that a structure protected by a kobject cannot be freed
> before its reference count goes to zero. The reference count is not under
> the direct control of the code which created the kobject. So that code must

kobject, so that code

> be notified asynchronously whenever the last reference to one of its
> kobjects goes away.
>
> Once you registered your kobject via kobject_add(), you must never use
> kfree() to free it directly. The only safe way is to use kobject_put(). It
> is good practice to always use kobject_put() after kobject_init() to avoid
> errors creeping in.
>
> This notification is done through a kobject's release() method. Usually
> such a method has a form like:
>
> void my_object_release(struct kobject *kobj)
> {
> struct my_object *mine = container_of(kobj, struct my_object, kobj);
>
> /* Perform any additional cleanup on this object, then... */
> kfree (mine);

No space after "kfree". :)

> }
>
> One important point cannot be overstated: every kobject must have a
> release() method, and the kobject must persist (in a consistent state)
> until that method is called. If these constraints are not met, the code is
> flawed. Note that the kernel will warn you if you forget to provide a
> release() method. Do not try to get rid of this warning by providing an
> "empty" release function, you will be mocked mercilessly by the kobject

s/,/;/

> maintainer if you attempt this.
>
...
>
> ksets
>
> A kset is merely a collection of kobjects that want to be associated with
> each other. There is no restriction that they be of the same ktype, but be
> very careful if they are not.
>
> A kset serves these functions:
>
...
>
> Kobject cleaning up
>
...
> Any initialization of the kobject that has been done will be automatically
> cleaned up by the kobject core. If a KOBJ_ADD uevent has been sent for
> the object, a corrisponding KOBJ_REMOVE uevent will be sent, and any other

corresponding

> sysfs housekeeping will be handled for the caller properly.
>
> In the future, the kobject_unregister() call will be going away to help
> clean up the kobject api.
>
>
> For a more complete example of using ksets and kobjects properly, see the
> sample/kobject/kset-example.c code.
> --

---
~Randy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/