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: Eric 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
425cb02912
Коммит
04256b4a8f
|
@ -147,6 +147,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
|
|||
{
|
||||
struct bin_attribute *bin_attr;
|
||||
|
||||
inode->i_private = sysfs_get(sd);
|
||||
inode->i_mapping->a_ops = &sysfs_aops;
|
||||
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
|
||||
inode->i_op = &sysfs_inode_operations;
|
||||
|
@ -214,6 +215,22 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
|
|||
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)
|
||||
{
|
||||
struct sysfs_addrm_cxt acxt;
|
||||
|
|
|
@ -29,6 +29,7 @@ struct kmem_cache *sysfs_dir_cachep;
|
|||
static const struct super_operations sysfs_ops = {
|
||||
.statfs = simple_statfs,
|
||||
.drop_inode = generic_delete_inode,
|
||||
.delete_inode = sysfs_delete_inode,
|
||||
};
|
||||
|
||||
struct sysfs_dirent sysfs_root = {
|
||||
|
|
|
@ -145,6 +145,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
|
|||
* inode.c
|
||||
*/
|
||||
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_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
|
||||
int sysfs_inode_init(void);
|
||||
|
|
Загрузка…
Ссылка в новой задаче