summaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
authorFelix Blyakher <felixb@sgi.com>2009-06-10 17:07:47 -0500
committerFelix Blyakher <felixb@sgi.com>2009-06-10 17:07:47 -0500
commit4e73e0eb633f8a1b5cbf20e7f42c6dbfec1d1ca7 (patch)
tree0cea46e43f0625244c3d06a71d6559e5ec5419ca /fs/sysfs
parent4156e735d3abde8e9243b5d22f7999dd3fffab2e (diff)
parent07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (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.c21
-rw-r--r--fs/sysfs/file.c16
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);