diff options
| author | Tejun Heo <tj@kernel.org> | 2013-11-28 14:54:40 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-11-29 21:10:48 -0500 |
| commit | ba7443bc656e5236c316b2acacc8b551f872910f (patch) | |
| tree | 08b9a7a0504ae77abc634419167958ce4e6c4e64 /fs/sysfs | |
| parent | 061447a496b915f1dc8f8c645c6825f856d2bbac (diff) | |
sysfs, kernfs: implement kernfs_create/destroy_root()
There currently is single kernfs hierarchy in the whole system which
is used for sysfs. kernfs needs to support multiple hierarchies to
allow other users. This patch introduces struct kernfs_root which
serves as the root of each kernfs hierarchy and implements
kernfs_create/destroy_root().
* Each kernfs_root is associated with a root sd (sysfs_dentry). The
root is freed when the root sd is released and kernfs_destory_root()
simply invokes kernfs_remove() on the root sd. sysfs_remove_one()
is updated to handle release of the root sd. Note that ps_iattr
update in sysfs_remove_one() is trivially updated for readability.
* Root sd's are now dynamically allocated using sysfs_new_dirent().
Update sysfs_alloc_ino() so that it gives out ino from 1 so that the
root sd still gets ino 1.
* While kernfs currently only points to the root sd, it'll soon grow
fields which are specific to each hierarchy. As determining a given
sd's root will be necessary, sd->s_dir.root is added. This backlink
fits better as a separate field in sd; however, sd->s_dir is inside
union with space to spare, so use it to save space and provide
kernfs_root() accessor to determine the root sd.
* As hierarchies may be destroyed now, each mount needs to hold onto
the hierarchy it's attached to. Update sysfs_fill_super() and
sysfs_kill_sb() so that they get and put the kernfs_root
respectively.
* sysfs_root is replaced with kernfs_root which is dynamically created
by invoking kernfs_create_root() from sysfs_init().
This patch doesn't introduce any visible behavior changes.
v2: kernfs_create_root() forgot to set @sd->priv. Fixed.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/sysfs')
| -rw-r--r-- | fs/sysfs/mount.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 7cbd1fce2826..0b5661b462f7 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -32,15 +32,8 @@ static const struct super_operations sysfs_ops = { | |||
| 32 | .evict_inode = sysfs_evict_inode, | 32 | .evict_inode = sysfs_evict_inode, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | static struct sysfs_dirent sysfs_root = { | 35 | static struct kernfs_root *sysfs_root; |
| 36 | .s_name = "", | 36 | struct sysfs_dirent *sysfs_root_sd; |
| 37 | .s_count = ATOMIC_INIT(1), | ||
| 38 | .s_flags = SYSFS_DIR, | ||
| 39 | .s_mode = S_IFDIR | S_IRUGO | S_IXUGO, | ||
| 40 | .s_ino = 1, | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct sysfs_dirent *sysfs_root_sd = &sysfs_root; | ||
| 44 | 37 | ||
| 45 | static int sysfs_fill_super(struct super_block *sb) | 38 | static int sysfs_fill_super(struct super_block *sb) |
| 46 | { | 39 | { |
| @@ -68,6 +61,7 @@ static int sysfs_fill_super(struct super_block *sb) | |||
| 68 | pr_debug("%s: could not get root dentry!\n", __func__); | 61 | pr_debug("%s: could not get root dentry!\n", __func__); |
| 69 | return -ENOMEM; | 62 | return -ENOMEM; |
| 70 | } | 63 | } |
| 64 | kernfs_get(sysfs_root_sd); | ||
| 71 | root->d_fsdata = sysfs_root_sd; | 65 | root->d_fsdata = sysfs_root_sd; |
| 72 | sb->s_root = root; | 66 | sb->s_root = root; |
| 73 | sb->s_d_op = &sysfs_dentry_ops; | 67 | sb->s_d_op = &sysfs_dentry_ops; |
| @@ -138,11 +132,15 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
| 138 | static void sysfs_kill_sb(struct super_block *sb) | 132 | static void sysfs_kill_sb(struct super_block *sb) |
| 139 | { | 133 | { |
| 140 | struct sysfs_super_info *info = sysfs_info(sb); | 134 | struct sysfs_super_info *info = sysfs_info(sb); |
| 141 | /* Remove the superblock from fs_supers/s_instances | 135 | struct sysfs_dirent *root_sd = sb->s_root->d_fsdata; |
| 136 | |||
| 137 | /* | ||
| 138 | * Remove the superblock from fs_supers/s_instances | ||
| 142 | * so we can't find it, before freeing sysfs_super_info. | 139 | * so we can't find it, before freeing sysfs_super_info. |
| 143 | */ | 140 | */ |
| 144 | kill_anon_super(sb); | 141 | kill_anon_super(sb); |
| 145 | free_sysfs_super_info(info); | 142 | free_sysfs_super_info(info); |
| 143 | kernfs_put(root_sd); | ||
| 146 | } | 144 | } |
| 147 | 145 | ||
| 148 | static struct file_system_type sysfs_fs_type = { | 146 | static struct file_system_type sysfs_fs_type = { |
| @@ -166,12 +164,21 @@ int __init sysfs_init(void) | |||
| 166 | if (err) | 164 | if (err) |
| 167 | goto out_err; | 165 | goto out_err; |
| 168 | 166 | ||
| 167 | sysfs_root = kernfs_create_root(NULL); | ||
| 168 | if (IS_ERR(sysfs_root)) { | ||
| 169 | err = PTR_ERR(sysfs_root); | ||
| 170 | goto out_err; | ||
| 171 | } | ||
| 172 | sysfs_root_sd = sysfs_root->sd; | ||
| 173 | |||
| 169 | err = register_filesystem(&sysfs_fs_type); | 174 | err = register_filesystem(&sysfs_fs_type); |
| 170 | if (err) | 175 | if (err) |
| 171 | goto out_err; | 176 | goto out_destroy_root; |
| 172 | 177 | ||
| 173 | return 0; | 178 | return 0; |
| 174 | 179 | ||
| 180 | out_destroy_root: | ||
| 181 | kernfs_destroy_root(sysfs_root); | ||
| 175 | out_err: | 182 | out_err: |
| 176 | kmem_cache_destroy(sysfs_dir_cachep); | 183 | kmem_cache_destroy(sysfs_dir_cachep); |
| 177 | sysfs_dir_cachep = NULL; | 184 | sysfs_dir_cachep = NULL; |
