diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/bin.c | 14 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 55 | ||||
-rw-r--r-- | fs/sysfs/file.c | 19 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 2 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 2 |
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 *)); |