Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 59123
b: refs/heads/master
c: eb36165
h: refs/heads/master
i:
  59121: 1341bfb
  59119: 320d9b3
v: v3
  • Loading branch information
Tejun Heo authored and Greg Kroah-Hartman committed Jul 11, 2007
1 parent 6ddf1b5 commit 1deb368
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2b29ac252afff87b8465b064ca2d9740cf1f6e52
refs/heads/master: eb36165353d0e5ac32b063f555acedcbaf6d3b75
64 changes: 49 additions & 15 deletions trunk/fs/sysfs/bin.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@

#include "sysfs.h"

struct bin_buffer {
struct mutex mutex;
void *buffer;
};

static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
Expand All @@ -36,7 +41,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
static ssize_t
read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
{
char *buffer = file->private_data;
struct bin_buffer *bb = file->private_data;
struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
Expand All @@ -49,17 +54,23 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
count = size - offs;
}

count = fill_read(dentry, buffer, offs, count);
mutex_lock(&bb->mutex);

count = fill_read(dentry, bb->buffer, offs, count);
if (count < 0)
return count;
goto out_unlock;

if (copy_to_user(userbuf, buffer, count))
return -EFAULT;
if (copy_to_user(userbuf, bb->buffer, count)) {
count = -EFAULT;
goto out_unlock;
}

pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);

*off = offs + count;

out_unlock:
mutex_unlock(&bb->mutex);
return count;
}

Expand All @@ -79,7 +90,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
static ssize_t write(struct file *file, const char __user *userbuf,
size_t bytes, loff_t *off)
{
char *buffer = file->private_data;
struct bin_buffer *bb = file->private_data;
struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
Expand All @@ -92,32 +103,46 @@ static ssize_t write(struct file *file, const char __user *userbuf,
count = size - offs;
}

if (copy_from_user(buffer, userbuf, count))
return -EFAULT;
mutex_lock(&bb->mutex);

if (copy_from_user(bb->buffer, userbuf, count)) {
count = -EFAULT;
goto out_unlock;
}

count = flush_write(dentry, buffer, offs, count);
count = flush_write(dentry, bb->buffer, offs, count);
if (count > 0)
*off = offs + count;

out_unlock:
mutex_unlock(&bb->mutex);
return count;
}

static int mmap(struct file *file, struct vm_area_struct *vma)
{
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct kobject *kobj = to_kobj(file->f_path.dentry->d_parent);
int rc;

if (!attr->mmap)
return -EINVAL;

return attr->mmap(kobj, attr, vma);
mutex_lock(&bb->mutex);
rc = attr->mmap(kobj, attr, vma);
mutex_unlock(&bb->mutex);

return rc;
}

static int open(struct inode * inode, struct file * file)
{
struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct bin_buffer *bb = NULL;
int error = -EINVAL;

if (!kobj || !attr)
Expand All @@ -135,14 +160,22 @@ static int open(struct inode * inode, struct file * file)
goto Error;

error = -ENOMEM;
file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!file->private_data)
bb = kzalloc(sizeof(*bb), GFP_KERNEL);
if (!bb)
goto Error;

bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!bb->buffer)
goto Error;

mutex_init(&bb->mutex);
file->private_data = bb;

error = 0;
goto Done;
goto Done;

Error:
kfree(bb);
module_put(attr->attr.owner);
Done:
if (error)
Expand All @@ -155,11 +188,12 @@ static int release(struct inode * inode, struct file * file)
struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
u8 * buffer = file->private_data;
struct bin_buffer *bb = file->private_data;

kobject_put(kobj);
module_put(attr->attr.owner);
kfree(buffer);
kfree(bb->buffer);
kfree(bb);
return 0;
}

Expand Down

0 comments on commit 1deb368

Please sign in to comment.