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.c64
1 files changed, 59 insertions, 5 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 8d4d839a9d88..fc4633378dc0 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -168,12 +168,12 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
168 ssize_t retval = 0; 168 ssize_t retval = 0;
169 169
170 down(&buffer->sem); 170 down(&buffer->sem);
171 if (buffer->orphaned) {
172 retval = -ENODEV;
173 goto out;
174 }
175 if (buffer->needs_read_fill) { 171 if (buffer->needs_read_fill) {
176 if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) 172 if (buffer->orphaned)
173 retval = -ENODEV;
174 else
175 retval = fill_read_buffer(file->f_path.dentry,buffer);
176 if (retval)
177 goto out; 177 goto out;
178 } 178 }
179 pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", 179 pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -629,6 +629,60 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
629} 629}
630EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); 630EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
631 631
632struct sysfs_schedule_callback_struct {
633 struct kobject *kobj;
634 void (*func)(void *);
635 void *data;
636 struct work_struct work;
637};
638
639static void sysfs_schedule_callback_work(struct work_struct *work)
640{
641 struct sysfs_schedule_callback_struct *ss = container_of(work,
642 struct sysfs_schedule_callback_struct, work);
643
644 (ss->func)(ss->data);
645 kobject_put(ss->kobj);
646 kfree(ss);
647}
648
649/**
650 * sysfs_schedule_callback - helper to schedule a callback for a kobject
651 * @kobj: object we're acting for.
652 * @func: callback function to invoke later.
653 * @data: argument to pass to @func.
654 *
655 * sysfs attribute methods must not unregister themselves or their parent
656 * kobject (which would amount to the same thing). Attempts to do so will
657 * deadlock, since unregistration is mutually exclusive with driver
658 * callbacks.
659 *
660 * Instead methods can call this routine, which will attempt to allocate
661 * and schedule a workqueue request to call back @func with @data as its
662 * argument in the workqueue's process context. @kobj will be pinned
663 * until @func returns.
664 *
665 * Returns 0 if the request was submitted, -ENOMEM if storage could not
666 * be allocated.
667 */
668int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
669 void *data)
670{
671 struct sysfs_schedule_callback_struct *ss;
672
673 ss = kmalloc(sizeof(*ss), GFP_KERNEL);
674 if (!ss)
675 return -ENOMEM;
676 kobject_get(kobj);
677 ss->kobj = kobj;
678 ss->func = func;
679 ss->data = data;
680 INIT_WORK(&ss->work, sysfs_schedule_callback_work);
681 schedule_work(&ss->work);
682 return 0;
683}
684EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
685
632 686
633EXPORT_SYMBOL_GPL(sysfs_create_file); 687EXPORT_SYMBOL_GPL(sysfs_create_file);
634EXPORT_SYMBOL_GPL(sysfs_remove_file); 688EXPORT_SYMBOL_GPL(sysfs_remove_file);