device_schedule_callback() needs a module reference
This 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> Cc: Satyam Sharma <satyam.sharma@gmail.com> Cc: Neil Brown <neilb@suse.de> Cc: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
fa1a8c23eb
commit
523ded71de
@@ -633,6 +633,7 @@ struct sysfs_schedule_callback_struct {
|
||||
struct kobject *kobj;
|
||||
void (*func)(void *);
|
||||
void *data;
|
||||
struct module *owner;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
@@ -643,6 +644,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
|
||||
|
||||
(ss->func)(ss->data);
|
||||
kobject_put(ss->kobj);
|
||||
module_put(ss->owner);
|
||||
kfree(ss);
|
||||
}
|
||||
|
||||
@@ -651,6 +653,7 @@ static void sysfs_schedule_callback_work(struct work_struct *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
|
||||
@@ -663,20 +666,25 @@ static void sysfs_schedule_callback_work(struct work_struct *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;
|
||||
|
Reference in New Issue
Block a user