diff options
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r-- | fs/sysfs/file.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 289c43a47263..b1606e07b7a3 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -446,11 +446,11 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) | |||
446 | if (buffer->event != atomic_read(&od->event)) | 446 | if (buffer->event != atomic_read(&od->event)) |
447 | goto trigger; | 447 | goto trigger; |
448 | 448 | ||
449 | return 0; | 449 | return DEFAULT_POLLMASK; |
450 | 450 | ||
451 | trigger: | 451 | trigger: |
452 | buffer->needs_read_fill = 1; | 452 | buffer->needs_read_fill = 1; |
453 | return POLLERR|POLLPRI; | 453 | return DEFAULT_POLLMASK|POLLERR|POLLPRI; |
454 | } | 454 | } |
455 | 455 | ||
456 | void sysfs_notify_dirent(struct sysfs_dirent *sd) | 456 | void sysfs_notify_dirent(struct sysfs_dirent *sd) |
@@ -667,6 +667,7 @@ struct sysfs_schedule_callback_struct { | |||
667 | struct work_struct work; | 667 | struct work_struct work; |
668 | }; | 668 | }; |
669 | 669 | ||
670 | static struct workqueue_struct *sysfs_workqueue; | ||
670 | static DEFINE_MUTEX(sysfs_workq_mutex); | 671 | static DEFINE_MUTEX(sysfs_workq_mutex); |
671 | static LIST_HEAD(sysfs_workq); | 672 | static LIST_HEAD(sysfs_workq); |
672 | static void sysfs_schedule_callback_work(struct work_struct *work) | 673 | static void sysfs_schedule_callback_work(struct work_struct *work) |
@@ -715,11 +716,20 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | |||
715 | mutex_lock(&sysfs_workq_mutex); | 716 | mutex_lock(&sysfs_workq_mutex); |
716 | list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) | 717 | list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) |
717 | if (ss->kobj == kobj) { | 718 | if (ss->kobj == kobj) { |
719 | module_put(owner); | ||
718 | mutex_unlock(&sysfs_workq_mutex); | 720 | mutex_unlock(&sysfs_workq_mutex); |
719 | return -EAGAIN; | 721 | return -EAGAIN; |
720 | } | 722 | } |
721 | mutex_unlock(&sysfs_workq_mutex); | 723 | mutex_unlock(&sysfs_workq_mutex); |
722 | 724 | ||
725 | if (sysfs_workqueue == NULL) { | ||
726 | sysfs_workqueue = create_workqueue("sysfsd"); | ||
727 | if (sysfs_workqueue == NULL) { | ||
728 | module_put(owner); | ||
729 | return -ENOMEM; | ||
730 | } | ||
731 | } | ||
732 | |||
723 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); | 733 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); |
724 | if (!ss) { | 734 | if (!ss) { |
725 | module_put(owner); | 735 | module_put(owner); |
@@ -735,7 +745,7 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | |||
735 | mutex_lock(&sysfs_workq_mutex); | 745 | mutex_lock(&sysfs_workq_mutex); |
736 | list_add_tail(&ss->workq_list, &sysfs_workq); | 746 | list_add_tail(&ss->workq_list, &sysfs_workq); |
737 | mutex_unlock(&sysfs_workq_mutex); | 747 | mutex_unlock(&sysfs_workq_mutex); |
738 | schedule_work(&ss->work); | 748 | queue_work(sysfs_workqueue, &ss->work); |
739 | return 0; | 749 | return 0; |
740 | } | 750 | } |
741 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); | 751 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); |