aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/kernfs/mount.c')
-rw-r--r--fs/kernfs/mount.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 95dcd1d558bb..f973ae9b05f1 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -68,6 +68,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
68 struct inode *inode; 68 struct inode *inode;
69 struct dentry *root; 69 struct dentry *root;
70 70
71 info->sb = sb;
71 sb->s_blocksize = PAGE_CACHE_SIZE; 72 sb->s_blocksize = PAGE_CACHE_SIZE;
72 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 73 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
73 sb->s_magic = magic; 74 sb->s_magic = magic;
@@ -167,12 +168,18 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
167 *new_sb_created = !sb->s_root; 168 *new_sb_created = !sb->s_root;
168 169
169 if (!sb->s_root) { 170 if (!sb->s_root) {
171 struct kernfs_super_info *info = kernfs_info(sb);
172
170 error = kernfs_fill_super(sb, magic); 173 error = kernfs_fill_super(sb, magic);
171 if (error) { 174 if (error) {
172 deactivate_locked_super(sb); 175 deactivate_locked_super(sb);
173 return ERR_PTR(error); 176 return ERR_PTR(error);
174 } 177 }
175 sb->s_flags |= MS_ACTIVE; 178 sb->s_flags |= MS_ACTIVE;
179
180 mutex_lock(&kernfs_mutex);
181 list_add(&info->node, &root->supers);
182 mutex_unlock(&kernfs_mutex);
176 } 183 }
177 184
178 return dget(sb->s_root); 185 return dget(sb->s_root);
@@ -191,6 +198,10 @@ void kernfs_kill_sb(struct super_block *sb)
191 struct kernfs_super_info *info = kernfs_info(sb); 198 struct kernfs_super_info *info = kernfs_info(sb);
192 struct kernfs_node *root_kn = sb->s_root->d_fsdata; 199 struct kernfs_node *root_kn = sb->s_root->d_fsdata;
193 200
201 mutex_lock(&kernfs_mutex);
202 list_del(&info->node);
203 mutex_unlock(&kernfs_mutex);
204
194 /* 205 /*
195 * Remove the superblock from fs_supers/s_instances 206 * Remove the superblock from fs_supers/s_instances
196 * so we can't find it, before freeing kernfs_super_info. 207 * so we can't find it, before freeing kernfs_super_info.
@@ -200,6 +211,36 @@ void kernfs_kill_sb(struct super_block *sb)
200 kernfs_put(root_kn); 211 kernfs_put(root_kn);
201} 212}
202 213
214/**
215 * kernfs_pin_sb: try to pin the superblock associated with a kernfs_root
216 * @kernfs_root: the kernfs_root in question
217 * @ns: the namespace tag
218 *
219 * Pin the superblock so the superblock won't be destroyed in subsequent
220 * operations. This can be used to block ->kill_sb() which may be useful
221 * for kernfs users which dynamically manage superblocks.
222 *
223 * Returns NULL if there's no superblock associated to this kernfs_root, or
224 * -EINVAL if the superblock is being freed.
225 */
226struct super_block *kernfs_pin_sb(struct kernfs_root *root, const void *ns)
227{
228 struct kernfs_super_info *info;
229 struct super_block *sb = NULL;
230
231 mutex_lock(&kernfs_mutex);
232 list_for_each_entry(info, &root->supers, node) {
233 if (info->ns == ns) {
234 sb = info->sb;
235 if (!atomic_inc_not_zero(&info->sb->s_active))
236 sb = ERR_PTR(-EINVAL);
237 break;
238 }
239 }
240 mutex_unlock(&kernfs_mutex);
241 return sb;
242}
243
203void __init kernfs_init(void) 244void __init kernfs_init(void)
204{ 245{
205 kernfs_node_cache = kmem_cache_create("kernfs_node_cache", 246 kernfs_node_cache = kmem_cache_create("kernfs_node_cache",