Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 59124
b: refs/heads/master
c: 0ab6608
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo authored and Greg Kroah-Hartman committed Jul 11, 2007
1 parent 1deb368 commit 49f84e2
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 114 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: eb36165353d0e5ac32b063f555acedcbaf6d3b75
refs/heads/master: 0ab66088c855eca68513bdd7442a426c4b374ced
95 changes: 62 additions & 33 deletions trunk/fs/sysfs/bin.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,28 @@
struct bin_buffer {
struct mutex mutex;
void *buffer;
int mmapped;
};

static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct kobject * kobj = to_kobj(dentry->d_parent);
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
int rc;

/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;

if (!attr->read)
return -EIO;
rc = -EIO;
if (attr->read)
rc = attr->read(kobj, buffer, off, count);

return attr->read(kobj, buffer, off, count);
sysfs_put_active_two(attr_sd);

return rc;
}

static ssize_t
Expand Down Expand Up @@ -79,12 +88,20 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct kobject *kobj = to_kobj(dentry->d_parent);
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
int rc;

/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;

if (!attr->write)
return -EIO;
rc = -EIO;
if (attr->write)
rc = attr->write(kobj, buffer, offset, count);

return attr->write(kobj, buffer, offset, count);
sysfs_put_active_two(attr_sd);

return rc;
}

static ssize_t write(struct file *file, const char __user *userbuf,
Expand Down Expand Up @@ -124,73 +141,85 @@ 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);
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
int rc;

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

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

/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;

rc = -EINVAL;
if (attr->mmap)
rc = attr->mmap(kobj, attr, vma);

if (rc == 0 && !bb->mmapped)
bb->mmapped = 1;
else
sysfs_put_active_two(attr_sd);

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;
int error;

if (!kobj || !attr)
goto Done;
/* need attr_sd for attr */
if (!sysfs_get_active(attr_sd))
return -ENODEV;

/* Grab the module reference for this attribute if we have one */
/* Grab the module reference for this attribute */
error = -ENODEV;
if (!try_module_get(attr->attr.owner))
goto Done;
if (!try_module_get(attr->attr.owner))
goto err_sput;

error = -EACCES;
if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
goto Error;
goto err_mput;
if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
goto Error;
goto err_mput;

error = -ENOMEM;
bb = kzalloc(sizeof(*bb), GFP_KERNEL);
if (!bb)
goto Error;
goto err_mput;

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

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

error = 0;
goto Done;
/* open succeeded, put active reference and pin attr_sd */
sysfs_put_active(attr_sd);
sysfs_get(attr_sd);
return 0;

Error:
kfree(bb);
err_mput:
module_put(attr->attr.owner);
Done:
if (error)
kobject_put(kobj);
err_sput:
sysfs_put_active(attr_sd);
kfree(bb);
return error;
}

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;
struct bin_buffer *bb = file->private_data;

kobject_put(kobj);
if (bb->mmapped)
sysfs_put_active_two(attr_sd);
sysfs_put(attr_sd);
module_put(attr->attr.owner);
kfree(bb->buffer);
kfree(bb);
Expand Down
28 changes: 25 additions & 3 deletions trunk/fs/sysfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
repeat:
parent_sd = sd->s_parent;

/* If @sd is being released after deletion, s_active is write
* locked. If @sd is cursor for directory walk or being
* released prematurely, s_active has no reader or writer.
*
* sysfs_deactivate() lies to lockdep that s_active is
* unlocked immediately. Lie one more time to cover the
* previous lie.
*/
if (!down_write_trylock(&sd->s_active))
rwsem_acquire(&sd->s_active.dep_map,
SYSFS_S_ACTIVE_DEACTIVATE, 0, _RET_IP_);
up_write(&sd->s_active);

if (sd->s_type & SYSFS_KOBJ_LINK)
sysfs_put(sd->s_elem.symlink.target_sd);
if (sd->s_type & SYSFS_COPY_NAME)
Expand Down Expand Up @@ -113,6 +126,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)

atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_event, 1);
init_rwsem(&sd->s_active);
INIT_LIST_HEAD(&sd->s_children);
INIT_LIST_HEAD(&sd->s_sibling);

Expand Down Expand Up @@ -371,7 +385,6 @@ static void remove_dir(struct dentry * d)
d_delete(d);
sd = d->d_fsdata;
list_del_init(&sd->s_sibling);
sysfs_put(sd);
if (d->d_inode)
simple_rmdir(parent->d_inode,d);

Expand All @@ -380,6 +393,9 @@ static void remove_dir(struct dentry * d)

mutex_unlock(&parent->d_inode->i_mutex);
dput(parent);

sysfs_deactivate(sd);
sysfs_put(sd);
}

void sysfs_remove_subdir(struct dentry * d)
Expand All @@ -390,6 +406,7 @@ void sysfs_remove_subdir(struct dentry * d)

static void __sysfs_remove_dir(struct dentry *dentry)
{
LIST_HEAD(removed);
struct sysfs_dirent * parent_sd;
struct sysfs_dirent * sd, * tmp;

Expand All @@ -403,12 +420,17 @@ static void __sysfs_remove_dir(struct dentry *dentry)
list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
if (!sd->s_type || !(sd->s_type & SYSFS_NOT_PINNED))
continue;
list_del_init(&sd->s_sibling);
list_move(&sd->s_sibling, &removed);
sysfs_drop_dentry(sd, dentry);
sysfs_put(sd);
}
mutex_unlock(&dentry->d_inode->i_mutex);

list_for_each_entry_safe(sd, tmp, &removed, s_sibling) {
list_del_init(&sd->s_sibling);
sysfs_deactivate(sd);
sysfs_put(sd);
}

remove_dir(dentry);
/**
* Drop reference from dget() on entrance.
Expand Down
Loading

0 comments on commit 49f84e2

Please sign in to comment.