diff options
author | Felix Blyakher <felixb@sgi.com> | 2009-06-10 17:07:47 -0500 |
---|---|---|
committer | Felix Blyakher <felixb@sgi.com> | 2009-06-10 17:07:47 -0500 |
commit | 4e73e0eb633f8a1b5cbf20e7f42c6dbfec1d1ca7 (patch) | |
tree | 0cea46e43f0625244c3d06a71d6559e5ec5419ca /fs/sysfs | |
parent | 4156e735d3abde8e9243b5d22f7999dd3fffab2e (diff) | |
parent | 07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/bin.c | 21 | ||||
-rw-r--r-- | fs/sysfs/file.c | 16 |
2 files changed, 20 insertions, 17 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 07703d3ff4a1..9345806c8853 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -157,14 +157,9 @@ static ssize_t write(struct file *file, const char __user *userbuf, count = size - offs; } - temp = kmalloc(count, GFP_KERNEL); - if (!temp) - return -ENOMEM; - - if (copy_from_user(temp, userbuf, count)) { - count = -EFAULT; - goto out_free; - } + temp = memdup_user(userbuf, count); + if (IS_ERR(temp)) + return PTR_ERR(temp); mutex_lock(&bb->mutex); @@ -176,8 +171,6 @@ static ssize_t write(struct file *file, const char __user *userbuf, if (count > 0) *off = offs + count; -out_free: - kfree(temp); return count; } @@ -234,7 +227,7 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return ret; } -static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page) +static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; @@ -242,15 +235,15 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page) int ret; if (!bb->vm_ops) - return -EINVAL; + return VM_FAULT_SIGBUS; if (!bb->vm_ops->page_mkwrite) return 0; if (!sysfs_get_active_two(attr_sd)) - return -EINVAL; + return VM_FAULT_SIGBUS; - ret = bb->vm_ops->page_mkwrite(vma, page); + ret = bb->vm_ops->page_mkwrite(vma, vmf); sysfs_put_active_two(attr_sd); return ret; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 289c43a47263..561a9c050cef 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) if (buffer->event != atomic_read(&od->event)) goto trigger; - return 0; + return DEFAULT_POLLMASK; trigger: buffer->needs_read_fill = 1; - return POLLERR|POLLPRI; + return DEFAULT_POLLMASK|POLLERR|POLLPRI; } void sysfs_notify_dirent(struct sysfs_dirent *sd) @@ -667,6 +667,7 @@ struct sysfs_schedule_callback_struct { struct work_struct work; }; +static struct workqueue_struct *sysfs_workqueue; static DEFINE_MUTEX(sysfs_workq_mutex); static LIST_HEAD(sysfs_workq); static void sysfs_schedule_callback_work(struct work_struct *work) @@ -715,11 +716,20 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), mutex_lock(&sysfs_workq_mutex); list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) if (ss->kobj == kobj) { + module_put(owner); mutex_unlock(&sysfs_workq_mutex); return -EAGAIN; } mutex_unlock(&sysfs_workq_mutex); + if (sysfs_workqueue == NULL) { + sysfs_workqueue = create_singlethread_workqueue("sysfsd"); + if (sysfs_workqueue == NULL) { + module_put(owner); + return -ENOMEM; + } + } + ss = kmalloc(sizeof(*ss), GFP_KERNEL); if (!ss) { module_put(owner); @@ -735,7 +745,7 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), mutex_lock(&sysfs_workq_mutex); list_add_tail(&ss->workq_list, &sysfs_workq); mutex_unlock(&sysfs_workq_mutex); - schedule_work(&ss->work); + queue_work(sysfs_workqueue, &ss->work); return 0; } EXPORT_SYMBOL_GPL(sysfs_schedule_callback); |