summaryrefslogtreecommitdiff
path: root/fs/sysfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/bin.c14
-rw-r--r--fs/sysfs/dir.c55
-rw-r--r--fs/sysfs/file.c19
-rw-r--r--fs/sysfs/mount.c2
-rw-r--r--fs/sysfs/sysfs.h2
5 files changed, 70 insertions, 22 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 98022e41cda1..e8f540d38d48 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -35,7 +35,7 @@ static ssize_t
read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
char *buffer = file->private_data;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
int ret;
@@ -81,7 +81,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
size_t count, loff_t * off)
{
char *buffer = file->private_data;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
@@ -105,7 +105,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
static int mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct bin_attribute *attr = to_bin_attr(dentry);
struct kobject *kobj = to_kobj(dentry->d_parent);
@@ -117,8 +117,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
static int open(struct inode * inode, struct file * file)
{
- struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
- struct bin_attribute * attr = to_bin_attr(file->f_dentry);
+ struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+ struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
int error = -EINVAL;
if (!kobj || !attr)
@@ -153,8 +153,8 @@ static int open(struct inode * inode, struct file * file)
static int release(struct inode * inode, struct file * file)
{
- struct kobject * kobj = to_kobj(file->f_dentry->d_parent);
- struct bin_attribute * attr = to_bin_attr(file->f_dentry);
+ struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
+ struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
u8 * buffer = file->private_data;
if (kobj)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 3aa3434621ca..511edef8b321 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -372,9 +372,54 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
return error;
}
+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+{
+ struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
+ struct sysfs_dirent *new_parent_sd, *sd;
+ int error;
+
+ if (!new_parent)
+ return -EINVAL;
+
+ old_parent_dentry = kobj->parent ?
+ kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
+ new_parent_dentry = new_parent->dentry;
+
+again:
+ mutex_lock(&old_parent_dentry->d_inode->i_mutex);
+ if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
+ mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+ goto again;
+ }
+
+ new_parent_sd = new_parent_dentry->d_fsdata;
+ sd = kobj->dentry->d_fsdata;
+
+ new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
+ strlen(kobj->name));
+ if (IS_ERR(new_dentry)) {
+ error = PTR_ERR(new_dentry);
+ goto out;
+ } else
+ error = 0;
+ d_add(new_dentry, NULL);
+ d_move(kobj->dentry, new_dentry);
+ dput(new_dentry);
+
+ /* Remove from old parent's list and insert into new parent's list. */
+ list_del_init(&sd->s_sibling);
+ list_add(&sd->s_sibling, &new_parent_sd->s_children);
+
+out:
+ mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
+ mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+
+ return error;
+}
+
static int sysfs_dir_open(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
mutex_lock(&dentry->d_inode->i_mutex);
@@ -387,7 +432,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
static int sysfs_dir_close(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
struct sysfs_dirent * cursor = file->private_data;
mutex_lock(&dentry->d_inode->i_mutex);
@@ -407,7 +452,7 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
struct sysfs_dirent *cursor = filp->private_data;
struct list_head *p, *q = &cursor->s_sibling;
@@ -464,7 +509,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
mutex_lock(&dentry->d_inode->i_mutex);
switch (origin) {
@@ -474,7 +519,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 298303b5a716..9cfe53e1e00d 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -154,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
down(&buffer->sem);
if (buffer->needs_read_fill) {
- if ((retval = fill_read_buffer(file->f_dentry,buffer)))
+ if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
goto out;
}
pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
+ /* if buf is assumed to contain a string, terminate it by \0,
+ so e.g. sscanf() can scan the string easily */
+ buffer->page[count] = 0;
return error ? -EFAULT : count;
}
@@ -242,7 +245,7 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
down(&buffer->sem);
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
- len = flush_write_buffer(file->f_dentry, buffer, len);
+ len = flush_write_buffer(file->f_path.dentry, buffer, len);
if (len > 0)
*ppos += len;
up(&buffer->sem);
@@ -251,8 +254,8 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
static int check_perm(struct inode * inode, struct file * file)
{
- struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
- struct attribute * attr = to_attr(file->f_dentry);
+ struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+ struct attribute * attr = to_attr(file->f_path.dentry);
struct sysfs_buffer * buffer;
struct sysfs_ops * ops = NULL;
int error = 0;
@@ -334,8 +337,8 @@ static int sysfs_open_file(struct inode * inode, struct file * filp)
static int sysfs_release(struct inode * inode, struct file * filp)
{
- struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
- struct attribute * attr = to_attr(filp->f_dentry);
+ struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
+ struct attribute * attr = to_attr(filp->f_path.dentry);
struct module * owner = attr->owner;
struct sysfs_buffer * buffer = filp->private_data;
@@ -369,8 +372,8 @@ static int sysfs_release(struct inode * inode, struct file * filp)
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
{
struct sysfs_buffer * buffer = filp->private_data;
- struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
- struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
+ struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
+ struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
int res = 0;
poll_wait(filp, &kobj->poll, wait);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 20551a1b8a56..e503f858fba8 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -16,7 +16,7 @@
struct vfsmount *sysfs_mount;
struct super_block * sysfs_sb = NULL;
-kmem_cache_t *sysfs_dir_cachep;
+struct kmem_cache *sysfs_dir_cachep;
static struct super_operations sysfs_ops = {
.statfs = simple_statfs,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 6f3d6bd52887..bd7cec295dab 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,6 +1,6 @@
extern struct vfsmount * sysfs_mount;
-extern kmem_cache_t *sysfs_dir_cachep;
+extern struct kmem_cache *sysfs_dir_cachep;
extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));