diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-04-26 03:12:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 13:57:32 -0400 |
commit | 523ded71de0c5e66973335bf99a80edfda9f401b (patch) | |
tree | 20f47e8ed91018977d9fb7f4169a6ef8db407b82 /drivers/base | |
parent | fa1a8c23eb7d3ded8a3c6d0e653339a2bc7fca9e (diff) |
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>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index f69305c7269d..8aa090da1cd7 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -480,9 +480,10 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) | |||
480 | EXPORT_SYMBOL_GPL(device_remove_bin_file); | 480 | EXPORT_SYMBOL_GPL(device_remove_bin_file); |
481 | 481 | ||
482 | /** | 482 | /** |
483 | * device_schedule_callback - helper to schedule a callback for a device | 483 | * device_schedule_callback_owner - helper to schedule a callback for a device |
484 | * @dev: device. | 484 | * @dev: device. |
485 | * @func: callback function to invoke later. | 485 | * @func: callback function to invoke later. |
486 | * @owner: module owning the callback routine | ||
486 | * | 487 | * |
487 | * Attribute methods must not unregister themselves or their parent device | 488 | * Attribute methods must not unregister themselves or their parent device |
488 | * (which would amount to the same thing). Attempts to do so will deadlock, | 489 | * (which would amount to the same thing). Attempts to do so will deadlock, |
@@ -493,20 +494,23 @@ EXPORT_SYMBOL_GPL(device_remove_bin_file); | |||
493 | * argument in the workqueue's process context. @dev will be pinned until | 494 | * argument in the workqueue's process context. @dev will be pinned until |
494 | * @func returns. | 495 | * @func returns. |
495 | * | 496 | * |
497 | * This routine is usually called via the inline device_schedule_callback(), | ||
498 | * which automatically sets @owner to THIS_MODULE. | ||
499 | * | ||
496 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | 500 | * Returns 0 if the request was submitted, -ENOMEM if storage could not |
497 | * be allocated. | 501 | * be allocated, -ENODEV if a reference to @owner isn't available. |
498 | * | 502 | * |
499 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an | 503 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an |
500 | * underlying sysfs routine (since it is intended for use by attribute | 504 | * underlying sysfs routine (since it is intended for use by attribute |
501 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. | 505 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. |
502 | */ | 506 | */ |
503 | int device_schedule_callback(struct device *dev, | 507 | int device_schedule_callback_owner(struct device *dev, |
504 | void (*func)(struct device *)) | 508 | void (*func)(struct device *), struct module *owner) |
505 | { | 509 | { |
506 | return sysfs_schedule_callback(&dev->kobj, | 510 | return sysfs_schedule_callback(&dev->kobj, |
507 | (void (*)(void *)) func, dev); | 511 | (void (*)(void *)) func, dev, owner); |
508 | } | 512 | } |
509 | EXPORT_SYMBOL_GPL(device_schedule_callback); | 513 | EXPORT_SYMBOL_GPL(device_schedule_callback_owner); |
510 | 514 | ||
511 | static void klist_children_get(struct klist_node *n) | 515 | static void klist_children_get(struct klist_node *n) |
512 | { | 516 | { |