* [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