diff options
Diffstat (limited to 'fs/ext4/sysfs.c')
| -rw-r--r-- | fs/ext4/sysfs.c | 65 | 
1 files changed, 47 insertions, 18 deletions
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c index e21afd52e7d7..1205261f130c 100644 --- a/fs/ext4/sysfs.c +++ b/fs/ext4/sysfs.c @@ -11,6 +11,7 @@  #include <linux/time.h>  #include <linux/fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <linux/proc_fs.h>  #include "ext4.h" @@ -329,6 +330,13 @@ static void ext4_sb_release(struct kobject *kobj)  	complete(&sbi->s_kobj_unregister);  } +static void ext4_kset_release(struct kobject *kobj) +{ +	struct kset *kset = container_of(kobj, struct kset, kobj); + +	kfree(kset); +} +  static const struct sysfs_ops ext4_attr_ops = {  	.show	= ext4_attr_show,  	.store	= ext4_attr_store, @@ -342,20 +350,18 @@ static struct kobj_type ext4_sb_ktype = {  static struct kobj_type ext4_ktype = {  	.sysfs_ops	= &ext4_attr_ops, +	.release	= ext4_kset_release,  }; -static struct kset ext4_kset = { -	.kobj   = {.ktype = &ext4_ktype}, -}; +static struct kset *ext4_kset;  static struct kobj_type ext4_feat_ktype = {  	.default_attrs	= ext4_feat_attrs,  	.sysfs_ops	= &ext4_attr_ops, +	.release	= (void (*)(struct kobject *))kfree,  }; -static struct kobject ext4_feat = { -	.kset	= &ext4_kset, -}; +static struct kobject *ext4_feat;  #define PROC_FILE_SHOW_DEFN(name) \  static int name##_open(struct inode *inode, struct file *file) \ @@ -392,12 +398,15 @@ int ext4_register_sysfs(struct super_block *sb)  	const struct ext4_proc_files *p;  	int err; -	sbi->s_kobj.kset = &ext4_kset; +	sbi->s_kobj.kset = ext4_kset;  	init_completion(&sbi->s_kobj_unregister);  	err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL,  				   "%s", sb->s_id); -	if (err) +	if (err) { +		kobject_put(&sbi->s_kobj); +		wait_for_completion(&sbi->s_kobj_unregister);  		return err; +	}  	if (ext4_proc_root)  		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); @@ -427,25 +436,45 @@ int __init ext4_init_sysfs(void)  {  	int ret; -	kobject_set_name(&ext4_kset.kobj, "ext4"); -	ext4_kset.kobj.parent = fs_kobj; -	ret = kset_register(&ext4_kset); +	ext4_kset = kzalloc(sizeof(*ext4_kset), GFP_KERNEL); +	if (!ext4_kset) +		return -ENOMEM; + +	kobject_set_name(&ext4_kset->kobj, "ext4"); +	ext4_kset->kobj.parent = fs_kobj; +	ext4_kset->kobj.ktype = &ext4_ktype; +	ret = kset_register(ext4_kset);  	if (ret) -		return ret; +		goto kset_err; + +	ext4_feat = kzalloc(sizeof(*ext4_feat), GFP_KERNEL); +	if (!ext4_feat) { +		ret = -ENOMEM; +		goto kset_err; +	} -	ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype, +	ext4_feat->kset = ext4_kset; +	ret = kobject_init_and_add(ext4_feat, &ext4_feat_ktype,  				   NULL, "features");  	if (ret) -		kset_unregister(&ext4_kset); -	else -		ext4_proc_root = proc_mkdir(proc_dirname, NULL); +		goto feat_err; + +	ext4_proc_root = proc_mkdir(proc_dirname, NULL); +	return ret; + +feat_err: +	kobject_put(ext4_feat); +kset_err: +	kset_unregister(ext4_kset); +	ext4_kset = NULL;  	return ret;  }  void ext4_exit_sysfs(void)  { -	kobject_put(&ext4_feat); -	kset_unregister(&ext4_kset); +	kobject_put(ext4_feat); +	kset_unregister(ext4_kset); +	ext4_kset = NULL;  	remove_proc_entry(proc_dirname, NULL);  	ext4_proc_root = NULL;  }  |