Re: [PATCH RFD] alternative kobject release wait mechanism
From: Cornelia Huck
Date: Wed Apr 18 2007 - 11:24:12 EST
On Wed, 18 Apr 2007 10:53:55 -0400 (EDT),
Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> Many drivers, especially those for hot-pluggable buses, register and
> unregister devices dynamically. These events can occur in time-critical
> situations, where the driver cannot afford to wait for all the references
> to be dropped when unregistering a device. It's okay to wait in a module
> exit routine, but to make things work the routine would have to wait for
> references to _all_ unregistered objects to go away, not just the
> references for the objects it unregisters at exit time.
Uh, yes, didn't think of that. I'd even say that's the majority of
devices allocated in a driver.
> BTW, Cornelia, there's a small problem with your patch set. You have
> kobject_init() try to grab a reference to kobj->owner, but it's quite
> possible for kobj->owner to contain uninitialized garbage since the rest
> of the kernel is still unaware of its existence. There's a patch below to
> fix things up. I've got a second patch which makes device_initialize()
> pass an owner to the embedded kobject, but I want to try it out a little
> before posting it. :-)
I was relying on the object being zeroed after allocation (and the
caller of kobject_initialize already setting ->owner), but passing an
owner via the initializing routine sounds saner. Thanks for looking at
that.
> Index: usb-2.6/include/linux/kobject.h
> ===================================================================
> --- usb-2.6.orig/include/linux/kobject.h
> +++ usb-2.6/include/linux/kobject.h
> @@ -71,7 +71,8 @@ static inline const char * kobject_name(
> return kobj->k_name;
> }
>
> -extern void kobject_init(struct kobject *);
> +extern void kobject_init_owner(struct kobject *, struct module *owner);
> +#define kobject_init(kobj) kobject_init_owner(kobj, THIS_MODULE)
> extern void kobject_cleanup(struct kobject *);
>
> extern int __must_check kobject_add(struct kobject *);
> @@ -84,7 +85,9 @@ extern int __must_check kobject_shadow_r
> const char *new_name);
> extern int __must_check kobject_move(struct kobject *, struct kobject *);
>
> -extern int __must_check kobject_register(struct kobject *);
> +extern int __must_check kobject_register_owner(struct kobject *,
> + struct module *owner);
> +#define kobject_register(kobj) kobject_register_owner(kobj, THIS_MODULE)
> extern void kobject_unregister(struct kobject *);
>
> extern struct kobject * kobject_get(struct kobject *);
> Index: usb-2.6/lib/kobject.c
> ===================================================================
> --- usb-2.6.orig/lib/kobject.c
> +++ usb-2.6/lib/kobject.c
> @@ -164,10 +164,11 @@ static void verify_dynamic_kobject_alloc
> #endif
>
> /**
> - * kobject_init - initialize object.
> + * kobject_init_onwer - initialize object.
> * @kobj: object in question.
> + * @owner: module owning @kobj.
> */
> -void kobject_init(struct kobject * kobj)
> +void kobject_init_owner(struct kobject * kobj, struct module *owner)
> {
> if (!kobj)
> return;
> @@ -178,6 +179,7 @@ void kobject_init(struct kobject * kobj)
> init_waitqueue_head(&kobj->poll);
> kobj->kset = kset_get(kobj->kset);
> /* Attempt to grab reference of owning module's kobject. */
> + kobj->owner = owner;
> mod_kobject_get(kobj->owner);
> }
>
> @@ -272,15 +274,16 @@ int kobject_add(struct kobject * kobj)
>
>
> /**
> - * kobject_register - initialize and add an object.
> + * kobject_register_owner - initialize and add an object.
> * @kobj: object in question.
> + * @owner: module owning @kobj.
> */
>
> -int kobject_register(struct kobject * kobj)
> +int kobject_register_owner(struct kobject * kobj, struct module *owner)
> {
> int error = -EINVAL;
> if (kobj) {
> - kobject_init(kobj);
> + kobject_init_owner(kobj, owner);
> error = kobject_add(kobj);
> if (!error)
> kobject_uevent(kobj, KOBJ_ADD);
> @@ -750,8 +753,8 @@ void subsys_remove_file(struct subsystem
> }
> #endif /* 0 */
>
> -EXPORT_SYMBOL(kobject_init);
> -EXPORT_SYMBOL(kobject_register);
> +EXPORT_SYMBOL(kobject_init_owner);
> +EXPORT_SYMBOL(kobject_register_owner);
> EXPORT_SYMBOL(kobject_unregister);
> EXPORT_SYMBOL(kobject_get);
> EXPORT_SYMBOL(kobject_put);
>
Hm, this means we always have an owner (until we explicitely call
kobject_{init,register}_owner(kobj, NULL)) - which may be unneeded in
some cases. But better to err on the safe side, I suppose.
-
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/