aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r--fs/sysfs/file.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index fc4633378dc0..db0413a411d6 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -633,6 +633,7 @@ struct sysfs_schedule_callback_struct {
633 struct kobject *kobj; 633 struct kobject *kobj;
634 void (*func)(void *); 634 void (*func)(void *);
635 void *data; 635 void *data;
636 struct module *owner;
636 struct work_struct work; 637 struct work_struct work;
637}; 638};
638 639
@@ -643,6 +644,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
643 644
644 (ss->func)(ss->data); 645 (ss->func)(ss->data);
645 kobject_put(ss->kobj); 646 kobject_put(ss->kobj);
647 module_put(ss->owner);
646 kfree(ss); 648 kfree(ss);
647} 649}
648 650
@@ -651,6 +653,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
651 * @kobj: object we're acting for. 653 * @kobj: object we're acting for.
652 * @func: callback function to invoke later. 654 * @func: callback function to invoke later.
653 * @data: argument to pass to @func. 655 * @data: argument to pass to @func.
656 * @owner: module owning the callback code
654 * 657 *
655 * sysfs attribute methods must not unregister themselves or their parent 658 * sysfs attribute methods must not unregister themselves or their parent
656 * kobject (which would amount to the same thing). Attempts to do so will 659 * 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)
663 * until @func returns. 666 * until @func returns.
664 * 667 *
665 * Returns 0 if the request was submitted, -ENOMEM if storage could not 668 * Returns 0 if the request was submitted, -ENOMEM if storage could not
666 * be allocated. 669 * be allocated, -ENODEV if a reference to @owner isn't available.
667 */ 670 */
668int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), 671int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
669 void *data) 672 void *data, struct module *owner)
670{ 673{
671 struct sysfs_schedule_callback_struct *ss; 674 struct sysfs_schedule_callback_struct *ss;
672 675
676 if (!try_module_get(owner))
677 return -ENODEV;
673 ss = kmalloc(sizeof(*ss), GFP_KERNEL); 678 ss = kmalloc(sizeof(*ss), GFP_KERNEL);
674 if (!ss) 679 if (!ss) {
680 module_put(owner);
675 return -ENOMEM; 681 return -ENOMEM;
682 }
676 kobject_get(kobj); 683 kobject_get(kobj);
677 ss->kobj = kobj; 684 ss->kobj = kobj;
678 ss->func = func; 685 ss->func = func;
679 ss->data = data; 686 ss->data = data;
687 ss->owner = owner;
680 INIT_WORK(&ss->work, sysfs_schedule_callback_work); 688 INIT_WORK(&ss->work, sysfs_schedule_callback_work);
681 schedule_work(&ss->work); 689 schedule_work(&ss->work);
682 return 0; 690 return 0;