* [PATCH (revised)] device_schedule_callback needs a module reference [not found] <a781481a0704090752u27140ee8vc93bd344c5005549@mail.gmail.com> @ 2007-04-09 15:07 ` Alan Stern 2007-04-10 13:13 ` Cornelia Huck 0 siblings, 1 reply; 4+ messages in thread From: Alan Stern @ 2007-04-09 15:07 UTC (permalink / raw) To: Andrew Morton, Satyam Sharma; +Cc: Neil Brown, Kernel development list This revised patch (as896b) fixes an oversight in the design of device_schedule_callback(). It is necessary to acquire a reference to the module owning the callback routine, to prevent the module from being unloaded before the callback can run. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> --- Index: usb-2.6/drivers/base/core.c =================================================================== --- usb-2.6.orig/drivers/base/core.c +++ usb-2.6/drivers/base/core.c @@ -431,9 +431,10 @@ void device_remove_bin_file(struct devic EXPORT_SYMBOL_GPL(device_remove_bin_file); /** - * device_schedule_callback - helper to schedule a callback for a device + * device_schedule_callback_owner - helper to schedule a callback for a device * @dev: device. * @func: callback function to invoke later. + * @owner: module owning the callback routine * * Attribute methods must not unregister themselves or their parent device * (which would amount to the same thing). Attempts to do so will deadlock, @@ -444,20 +445,23 @@ EXPORT_SYMBOL_GPL(device_remove_bin_file * argument in the workqueue's process context. @dev will be pinned until * @func returns. * + * This routine is usually called via the inline device_schedule_callback(), + * which automatically sets @owner to THIS_MODULE. + * * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated. + * be allocated, -ENODEV if a reference to @owner isn't available. * * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an * underlying sysfs routine (since it is intended for use by attribute * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. */ -int device_schedule_callback(struct device *dev, - void (*func)(struct device *)) +int device_schedule_callback_owner(struct device *dev, + void (*func)(struct device *), struct module *owner) { return sysfs_schedule_callback(&dev->kobj, - (void (*)(void *)) func, dev); + (void (*)(void *)) func, dev, owner); } -EXPORT_SYMBOL_GPL(device_schedule_callback); +EXPORT_SYMBOL_GPL(device_schedule_callback_owner); static void klist_children_get(struct klist_node *n) { Index: usb-2.6/fs/sysfs/file.c =================================================================== --- usb-2.6.orig/fs/sysfs/file.c +++ usb-2.6/fs/sysfs/file.c @@ -647,6 +647,7 @@ struct sysfs_schedule_callback_struct { struct kobject *kobj; void (*func)(void *); void *data; + struct module *owner; struct work_struct work; }; @@ -657,6 +658,7 @@ static void sysfs_schedule_callback_work (ss->func)(ss->data); kobject_put(ss->kobj); + module_put(ss->owner); kfree(ss); } @@ -665,6 +667,7 @@ static void sysfs_schedule_callback_work * @kobj: object we're acting for. * @func: callback function to invoke later. * @data: argument to pass to @func. + * @owner: module owning the callback code * * sysfs attribute methods must not unregister themselves or their parent * kobject (which would amount to the same thing). Attempts to do so will @@ -677,20 +680,25 @@ static void sysfs_schedule_callback_work * until @func returns. * * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated. + * be allocated, -ENODEV if a reference to @owner isn't available. */ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), - void *data) + void *data, struct module *owner) { struct sysfs_schedule_callback_struct *ss; + if (!try_module_get(owner)) + return -ENODEV; ss = kmalloc(sizeof(*ss), GFP_KERNEL); - if (!ss) + if (!ss) { + module_put(owner); return -ENOMEM; + } kobject_get(kobj); ss->kobj = kobj; ss->func = func; ss->data = data; + ss->owner = owner; INIT_WORK(&ss->work, sysfs_schedule_callback_work); schedule_work(&ss->work); return 0; Index: usb-2.6/include/linux/device.h =================================================================== --- usb-2.6.orig/include/linux/device.h +++ usb-2.6/include/linux/device.h @@ -369,8 +369,14 @@ extern int __must_check device_create_bi struct bin_attribute *attr); extern void device_remove_bin_file(struct device *dev, struct bin_attribute *attr); -extern int device_schedule_callback(struct device *dev, - void (*func)(struct device *)); +extern int device_schedule_callback_owner(struct device *dev, + void (*func)(struct device *), struct module *owner); + +static inline int device_schedule_callback(struct device *dev, + void (*func)(struct device *)) +{ + return device_schedule_callback_owner(dev, func, THIS_MODULE); +} /* device resource management */ typedef void (*dr_release_t)(struct device *dev, void *res); Index: usb-2.6/include/linux/sysfs.h =================================================================== --- usb-2.6.orig/include/linux/sysfs.h +++ usb-2.6/include/linux/sysfs.h @@ -80,7 +80,7 @@ struct sysfs_ops { #ifdef CONFIG_SYSFS extern int sysfs_schedule_callback(struct kobject *kobj, - void (*func)(void *), void *data); + void (*func)(void *), void *data, struct module *owner); extern int __must_check sysfs_create_dir(struct kobject *, struct dentry *); @@ -138,7 +138,7 @@ extern int __must_check sysfs_init(void) #else /* CONFIG_SYSFS */ static inline int sysfs_schedule_callback(struct kobject *kobj, - void (*func)(void *), void *data) + void (*func)(void *), void *data, struct module *owner) { return -ENOSYS; } ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH (revised)] device_schedule_callback needs a module reference 2007-04-09 15:07 ` [PATCH (revised)] device_schedule_callback needs a module reference Alan Stern @ 2007-04-10 13:13 ` Cornelia Huck 2007-04-10 16:46 ` Alan Stern 0 siblings, 1 reply; 4+ messages in thread From: Cornelia Huck @ 2007-04-10 13:13 UTC (permalink / raw) To: Alan Stern Cc: Andrew Morton, Satyam Sharma, Neil Brown, Kernel development list, linux-s390 On Mon, 9 Apr 2007 11:07:22 -0400 (EDT), Alan Stern <stern@rowland.harvard.edu> wrote: > This revised patch (as896b) fixes an oversight in the design of > device_schedule_callback(). It is necessary to acquire a reference to > the module owning the callback routine, to prevent the module from > being unloaded before the callback can run. > > Signed-off-by: Alan Stern <stern@rowland.harvard.edu> <snip> > Index: usb-2.6/include/linux/device.h > =================================================================== > --- usb-2.6.orig/include/linux/device.h > +++ usb-2.6/include/linux/device.h > @@ -369,8 +369,14 @@ extern int __must_check device_create_bi > struct bin_attribute *attr); > extern void device_remove_bin_file(struct device *dev, > struct bin_attribute *attr); > -extern int device_schedule_callback(struct device *dev, > - void (*func)(struct device *)); > +extern int device_schedule_callback_owner(struct device *dev, > + void (*func)(struct device *), struct module *owner); > + > +static inline int device_schedule_callback(struct device *dev, > + void (*func)(struct device *)) > +{ > + return device_schedule_callback_owner(dev, func, THIS_MODULE); > +} > > /* device resource management */ > typedef void (*dr_release_t)(struct device *dev, void *res); Whoops: In file included from include/linux/interrupt.h:15, from include/asm/hardirq.h:18, from include/linux/hardirq.h:7, from include/asm-generic/local.h:5, from include/asm/local.h:1, from include/linux/module.h:19, from arch/s390/kernel/time.c:16: include/linux/device.h: In function 'device_schedule_callback': include/linux/device.h:374: error: 'THIS_MODULE' undeclared (first use in this function) include/linux/device.h:374: error: (Each undeclared identifier is reported only once include/linux/device.h:374: error: for each function it appears in.) Maybe better move the implementation of device_schedule_callback() to drivers/base/core.c? (Though I'm not sure why include/asm-s390/hardirq.h includes linux/interrupt.h, and e.g. include/asm-i386/hardirq.h doesn't.) ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH (revised)] device_schedule_callback needs a module reference 2007-04-10 13:13 ` Cornelia Huck @ 2007-04-10 16:46 ` Alan Stern 2007-04-10 22:32 ` Andrew Morton 0 siblings, 1 reply; 4+ messages in thread From: Alan Stern @ 2007-04-10 16:46 UTC (permalink / raw) To: Cornelia Huck Cc: Andrew Morton, Satyam Sharma, Neil Brown, Kernel development list, linux-s390 On Tue, 10 Apr 2007, Cornelia Huck wrote: > Whoops: > > In file included from include/linux/interrupt.h:15, > from include/asm/hardirq.h:18, > from include/linux/hardirq.h:7, > from include/asm-generic/local.h:5, > from include/asm/local.h:1, > from include/linux/module.h:19, > from arch/s390/kernel/time.c:16: > include/linux/device.h: In function 'device_schedule_callback': > include/linux/device.h:374: error: 'THIS_MODULE' undeclared (first use in this function) > include/linux/device.h:374: error: (Each undeclared identifier is reported only once > include/linux/device.h:374: error: for each function it appears in.) > > Maybe better move the implementation of device_schedule_callback() to > drivers/base/core.c? (Though I'm not sure why > include/asm-s390/hardirq.h includes linux/interrupt.h, and e.g. > include/asm-i386/hardirq.h doesn't.) I don't think moving device_schedule_callback() is the answer. For one thing, the implementation _has_ to be compiled in the calling module so that THIS_MODULE will have the correct value. If it were compiled in drivers/base/core.c then it wouldn't refer to the caller's module. The real problem is bad nesting of #includes. Maybe changing include/asm-s390/hardirq.h not to include linux/interrupt.h will be feasible. Or perhaps it would be better to move the definition of THIS_MODULE in linux/module.h up before all the #include lines, since it seems reasonable that a file indirectly included by module.h might need to use THIS_MODULE. Alan Stern ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH (revised)] device_schedule_callback needs a module reference 2007-04-10 16:46 ` Alan Stern @ 2007-04-10 22:32 ` Andrew Morton 0 siblings, 0 replies; 4+ messages in thread From: Andrew Morton @ 2007-04-10 22:32 UTC (permalink / raw) To: Alan Stern Cc: Cornelia Huck, Satyam Sharma, Neil Brown, Kernel development list, linux-s390 On Tue, 10 Apr 2007 12:46:11 -0400 (EDT) Alan Stern <stern@rowland.harvard.edu> wrote: > On Tue, 10 Apr 2007, Cornelia Huck wrote: > > > Whoops: > > > > In file included from include/linux/interrupt.h:15, > > from include/asm/hardirq.h:18, > > from include/linux/hardirq.h:7, > > from include/asm-generic/local.h:5, > > from include/asm/local.h:1, > > from include/linux/module.h:19, > > from arch/s390/kernel/time.c:16: > > include/linux/device.h: In function 'device_schedule_callback': > > include/linux/device.h:374: error: 'THIS_MODULE' undeclared (first use in this function) > > include/linux/device.h:374: error: (Each undeclared identifier is reported only once > > include/linux/device.h:374: error: for each function it appears in.) > > > > Maybe better move the implementation of device_schedule_callback() to > > drivers/base/core.c? (Though I'm not sure why > > include/asm-s390/hardirq.h includes linux/interrupt.h, and e.g. > > include/asm-i386/hardirq.h doesn't.) > > I don't think moving device_schedule_callback() is the answer. For one > thing, the implementation _has_ to be compiled in the calling module so > that THIS_MODULE will have the correct value. If it were compiled in > drivers/base/core.c then it wouldn't refer to the caller's module. > > The real problem is bad nesting of #includes. Maybe changing > include/asm-s390/hardirq.h not to include linux/interrupt.h will be > feasible. > > Or perhaps it would be better to move the definition of THIS_MODULE in > linux/module.h up before all the #include lines, since it seems reasonable > that a file indirectly included by module.h might need to use THIS_MODULE. > <holds nose> --- a/include/linux/device.h~device_schedule_callback-needs-a-module-reference-fix +++ a/include/linux/device.h @@ -369,11 +369,9 @@ extern void device_remove_bin_file(struc extern int device_schedule_callback_owner(struct device *dev, void (*func)(struct device *), struct module *owner); -static inline int device_schedule_callback(struct device *dev, - void (*func)(struct device *)) -{ - return device_schedule_callback_owner(dev, func, THIS_MODULE); -} +/* This is a macro to avoid include problems with THIS_MODULE */ +#define device_schedule_callback(dev, func) \ + device_schedule_callback_owner(dev, func, THIS_MODULE) /* device resource management */ typedef void (*dr_release_t)(struct device *dev, void *res); _ ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-04-10 22:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <a781481a0704090752u27140ee8vc93bd344c5005549@mail.gmail.com>
2007-04-09 15:07 ` [PATCH (revised)] device_schedule_callback needs a module reference Alan Stern
2007-04-10 13:13 ` Cornelia Huck
2007-04-10 16:46 ` Alan Stern
2007-04-10 22:32 ` Andrew Morton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
Powered by JetHome