Commit 04256b4a authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Greg Kroah-Hartman

sysfs: reference sysfs_dirent from sysfs inodes

The sysfs_dirent serves as both an inode and a directory entry
for sysfs.  To prevent the sysfs inode numbers from being freed
prematurely hold a reference to sysfs_dirent from the sysfs inode.

[akpm@linux-foundation.org: add comment]
Signed-off-by: default avatarEric W. Biederman <ebiederm@aristanetworks.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 425cb029
...@@ -147,6 +147,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) ...@@ -147,6 +147,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
{ {
struct bin_attribute *bin_attr; struct bin_attribute *bin_attr;
inode->i_private = sysfs_get(sd);
inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
inode->i_op = &sysfs_inode_operations; inode->i_op = &sysfs_inode_operations;
...@@ -214,6 +215,22 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) ...@@ -214,6 +215,22 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
return inode; return inode;
} }
/*
* The sysfs_dirent serves as both an inode and a directory entry for sysfs.
* To prevent the sysfs inode numbers from being freed prematurely we take a
* reference to sysfs_dirent from the sysfs inode. A
* super_operations.delete_inode() implementation is needed to drop that
* reference upon inode destruction.
*/
void sysfs_delete_inode(struct inode *inode)
{
struct sysfs_dirent *sd = inode->i_private;
truncate_inode_pages(&inode->i_data, 0);
clear_inode(inode);
sysfs_put(sd);
}
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
{ {
struct sysfs_addrm_cxt acxt; struct sysfs_addrm_cxt acxt;
......
...@@ -29,6 +29,7 @@ struct kmem_cache *sysfs_dir_cachep; ...@@ -29,6 +29,7 @@ struct kmem_cache *sysfs_dir_cachep;
static const struct super_operations sysfs_ops = { static const struct super_operations sysfs_ops = {
.statfs = simple_statfs, .statfs = simple_statfs,
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.delete_inode = sysfs_delete_inode,
}; };
struct sysfs_dirent sysfs_root = { struct sysfs_dirent sysfs_root = {
......
...@@ -145,6 +145,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) ...@@ -145,6 +145,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
* inode.c * inode.c
*/ */
struct inode *sysfs_get_inode(struct sysfs_dirent *sd); struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
void sysfs_delete_inode(struct inode *inode);
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
int sysfs_inode_init(void); int sysfs_inode_init(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment