162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/kernfs/mount.c - kernfs mount implementation 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2001-3 Patrick Mochel 662306a36Sopenharmony_ci * Copyright (c) 2007 SUSE Linux Products GmbH 762306a36Sopenharmony_ci * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/mount.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/magic.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/pagemap.h> 1662306a36Sopenharmony_ci#include <linux/namei.h> 1762306a36Sopenharmony_ci#include <linux/seq_file.h> 1862306a36Sopenharmony_ci#include <linux/exportfs.h> 1962306a36Sopenharmony_ci#include <linux/uuid.h> 2062306a36Sopenharmony_ci#include <linux/statfs.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "kernfs-internal.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct kmem_cache *kernfs_node_cache, *kernfs_iattrs_cache; 2562306a36Sopenharmony_cistruct kernfs_global_locks *kernfs_locks; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct kernfs_root *root = kernfs_root(kernfs_dentry_node(dentry)); 3062306a36Sopenharmony_ci struct kernfs_syscall_ops *scops = root->syscall_ops; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if (scops && scops->show_options) 3362306a36Sopenharmony_ci return scops->show_options(sf, root); 3462306a36Sopenharmony_ci return 0; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic int kernfs_sop_show_path(struct seq_file *sf, struct dentry *dentry) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci struct kernfs_node *node = kernfs_dentry_node(dentry); 4062306a36Sopenharmony_ci struct kernfs_root *root = kernfs_root(node); 4162306a36Sopenharmony_ci struct kernfs_syscall_ops *scops = root->syscall_ops; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (scops && scops->show_path) 4462306a36Sopenharmony_ci return scops->show_path(sf, node, root); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci seq_dentry(sf, dentry, " \t\n\\"); 4762306a36Sopenharmony_ci return 0; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic int kernfs_statfs(struct dentry *dentry, struct kstatfs *buf) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci simple_statfs(dentry, buf); 5362306a36Sopenharmony_ci buf->f_fsid = uuid_to_fsid(dentry->d_sb->s_uuid.b); 5462306a36Sopenharmony_ci return 0; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciconst struct super_operations kernfs_sops = { 5862306a36Sopenharmony_ci .statfs = kernfs_statfs, 5962306a36Sopenharmony_ci .drop_inode = generic_delete_inode, 6062306a36Sopenharmony_ci .evict_inode = kernfs_evict_inode, 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci .show_options = kernfs_sop_show_options, 6362306a36Sopenharmony_ci .show_path = kernfs_sop_show_path, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int kernfs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, 6762306a36Sopenharmony_ci struct inode *parent) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct kernfs_node *kn = inode->i_private; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if (*max_len < 2) { 7262306a36Sopenharmony_ci *max_len = 2; 7362306a36Sopenharmony_ci return FILEID_INVALID; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci *max_len = 2; 7762306a36Sopenharmony_ci *(u64 *)fh = kn->id; 7862306a36Sopenharmony_ci return FILEID_KERNFS; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic struct dentry *__kernfs_fh_to_dentry(struct super_block *sb, 8262306a36Sopenharmony_ci struct fid *fid, int fh_len, 8362306a36Sopenharmony_ci int fh_type, bool get_parent) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct kernfs_super_info *info = kernfs_info(sb); 8662306a36Sopenharmony_ci struct kernfs_node *kn; 8762306a36Sopenharmony_ci struct inode *inode; 8862306a36Sopenharmony_ci u64 id; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (fh_len < 2) 9162306a36Sopenharmony_ci return NULL; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci switch (fh_type) { 9462306a36Sopenharmony_ci case FILEID_KERNFS: 9562306a36Sopenharmony_ci id = *(u64 *)fid; 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci case FILEID_INO32_GEN: 9862306a36Sopenharmony_ci case FILEID_INO32_GEN_PARENT: 9962306a36Sopenharmony_ci /* 10062306a36Sopenharmony_ci * blk_log_action() exposes "LOW32,HIGH32" pair without 10162306a36Sopenharmony_ci * type and userland can call us with generic fid 10262306a36Sopenharmony_ci * constructed from them. Combine it back to ID. See 10362306a36Sopenharmony_ci * blk_log_action(). 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci id = ((u64)fid->i32.gen << 32) | fid->i32.ino; 10662306a36Sopenharmony_ci break; 10762306a36Sopenharmony_ci default: 10862306a36Sopenharmony_ci return NULL; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci kn = kernfs_find_and_get_node_by_id(info->root, id); 11262306a36Sopenharmony_ci if (!kn) 11362306a36Sopenharmony_ci return ERR_PTR(-ESTALE); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (get_parent) { 11662306a36Sopenharmony_ci struct kernfs_node *parent; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci parent = kernfs_get_parent(kn); 11962306a36Sopenharmony_ci kernfs_put(kn); 12062306a36Sopenharmony_ci kn = parent; 12162306a36Sopenharmony_ci if (!kn) 12262306a36Sopenharmony_ci return ERR_PTR(-ESTALE); 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci inode = kernfs_get_inode(sb, kn); 12662306a36Sopenharmony_ci kernfs_put(kn); 12762306a36Sopenharmony_ci if (!inode) 12862306a36Sopenharmony_ci return ERR_PTR(-ESTALE); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return d_obtain_alias(inode); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic struct dentry *kernfs_fh_to_dentry(struct super_block *sb, 13462306a36Sopenharmony_ci struct fid *fid, int fh_len, 13562306a36Sopenharmony_ci int fh_type) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci return __kernfs_fh_to_dentry(sb, fid, fh_len, fh_type, false); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic struct dentry *kernfs_fh_to_parent(struct super_block *sb, 14162306a36Sopenharmony_ci struct fid *fid, int fh_len, 14262306a36Sopenharmony_ci int fh_type) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci return __kernfs_fh_to_dentry(sb, fid, fh_len, fh_type, true); 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic struct dentry *kernfs_get_parent_dentry(struct dentry *child) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct kernfs_node *kn = kernfs_dentry_node(child); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent)); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic const struct export_operations kernfs_export_ops = { 15562306a36Sopenharmony_ci .encode_fh = kernfs_encode_fh, 15662306a36Sopenharmony_ci .fh_to_dentry = kernfs_fh_to_dentry, 15762306a36Sopenharmony_ci .fh_to_parent = kernfs_fh_to_parent, 15862306a36Sopenharmony_ci .get_parent = kernfs_get_parent_dentry, 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/** 16262306a36Sopenharmony_ci * kernfs_root_from_sb - determine kernfs_root associated with a super_block 16362306a36Sopenharmony_ci * @sb: the super_block in question 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * Return: the kernfs_root associated with @sb. If @sb is not a kernfs one, 16662306a36Sopenharmony_ci * %NULL is returned. 16762306a36Sopenharmony_ci */ 16862306a36Sopenharmony_cistruct kernfs_root *kernfs_root_from_sb(struct super_block *sb) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci if (sb->s_op == &kernfs_sops) 17162306a36Sopenharmony_ci return kernfs_info(sb)->root; 17262306a36Sopenharmony_ci return NULL; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* 17662306a36Sopenharmony_ci * find the next ancestor in the path down to @child, where @parent was the 17762306a36Sopenharmony_ci * ancestor whose descendant we want to find. 17862306a36Sopenharmony_ci * 17962306a36Sopenharmony_ci * Say the path is /a/b/c/d. @child is d, @parent is %NULL. We return the root 18062306a36Sopenharmony_ci * node. If @parent is b, then we return the node for c. 18162306a36Sopenharmony_ci * Passing in d as @parent is not ok. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_cistatic struct kernfs_node *find_next_ancestor(struct kernfs_node *child, 18462306a36Sopenharmony_ci struct kernfs_node *parent) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci if (child == parent) { 18762306a36Sopenharmony_ci pr_crit_once("BUG in find_next_ancestor: called with parent == child"); 18862306a36Sopenharmony_ci return NULL; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci while (child->parent != parent) { 19262306a36Sopenharmony_ci if (!child->parent) 19362306a36Sopenharmony_ci return NULL; 19462306a36Sopenharmony_ci child = child->parent; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return child; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/** 20162306a36Sopenharmony_ci * kernfs_node_dentry - get a dentry for the given kernfs_node 20262306a36Sopenharmony_ci * @kn: kernfs_node for which a dentry is needed 20362306a36Sopenharmony_ci * @sb: the kernfs super_block 20462306a36Sopenharmony_ci * 20562306a36Sopenharmony_ci * Return: the dentry pointer 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_cistruct dentry *kernfs_node_dentry(struct kernfs_node *kn, 20862306a36Sopenharmony_ci struct super_block *sb) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct dentry *dentry; 21162306a36Sopenharmony_ci struct kernfs_node *knparent = NULL; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci BUG_ON(sb->s_op != &kernfs_sops); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci dentry = dget(sb->s_root); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Check if this is the root kernfs_node */ 21862306a36Sopenharmony_ci if (!kn->parent) 21962306a36Sopenharmony_ci return dentry; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci knparent = find_next_ancestor(kn, NULL); 22262306a36Sopenharmony_ci if (WARN_ON(!knparent)) { 22362306a36Sopenharmony_ci dput(dentry); 22462306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci do { 22862306a36Sopenharmony_ci struct dentry *dtmp; 22962306a36Sopenharmony_ci struct kernfs_node *kntmp; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (kn == knparent) 23262306a36Sopenharmony_ci return dentry; 23362306a36Sopenharmony_ci kntmp = find_next_ancestor(kn, knparent); 23462306a36Sopenharmony_ci if (WARN_ON(!kntmp)) { 23562306a36Sopenharmony_ci dput(dentry); 23662306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci dtmp = lookup_positive_unlocked(kntmp->name, dentry, 23962306a36Sopenharmony_ci strlen(kntmp->name)); 24062306a36Sopenharmony_ci dput(dentry); 24162306a36Sopenharmony_ci if (IS_ERR(dtmp)) 24262306a36Sopenharmony_ci return dtmp; 24362306a36Sopenharmony_ci knparent = kntmp; 24462306a36Sopenharmony_ci dentry = dtmp; 24562306a36Sopenharmony_ci } while (true); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *kfc) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct kernfs_super_info *info = kernfs_info(sb); 25162306a36Sopenharmony_ci struct kernfs_root *kf_root = kfc->root; 25262306a36Sopenharmony_ci struct inode *inode; 25362306a36Sopenharmony_ci struct dentry *root; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci info->sb = sb; 25662306a36Sopenharmony_ci /* Userspace would break if executables or devices appear on sysfs */ 25762306a36Sopenharmony_ci sb->s_iflags |= SB_I_NOEXEC | SB_I_NODEV; 25862306a36Sopenharmony_ci sb->s_blocksize = PAGE_SIZE; 25962306a36Sopenharmony_ci sb->s_blocksize_bits = PAGE_SHIFT; 26062306a36Sopenharmony_ci sb->s_magic = kfc->magic; 26162306a36Sopenharmony_ci sb->s_op = &kernfs_sops; 26262306a36Sopenharmony_ci sb->s_xattr = kernfs_xattr_handlers; 26362306a36Sopenharmony_ci if (info->root->flags & KERNFS_ROOT_SUPPORT_EXPORTOP) 26462306a36Sopenharmony_ci sb->s_export_op = &kernfs_export_ops; 26562306a36Sopenharmony_ci sb->s_time_gran = 1; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* sysfs dentries and inodes don't require IO to create */ 26862306a36Sopenharmony_ci sb->s_shrink.seeks = 0; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* get root inode, initialize and unlock it */ 27162306a36Sopenharmony_ci down_read(&kf_root->kernfs_rwsem); 27262306a36Sopenharmony_ci inode = kernfs_get_inode(sb, info->root->kn); 27362306a36Sopenharmony_ci up_read(&kf_root->kernfs_rwsem); 27462306a36Sopenharmony_ci if (!inode) { 27562306a36Sopenharmony_ci pr_debug("kernfs: could not get root inode\n"); 27662306a36Sopenharmony_ci return -ENOMEM; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* instantiate and link root dentry */ 28062306a36Sopenharmony_ci root = d_make_root(inode); 28162306a36Sopenharmony_ci if (!root) { 28262306a36Sopenharmony_ci pr_debug("%s: could not get root dentry!\n", __func__); 28362306a36Sopenharmony_ci return -ENOMEM; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci sb->s_root = root; 28662306a36Sopenharmony_ci sb->s_d_op = &kernfs_dops; 28762306a36Sopenharmony_ci return 0; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic int kernfs_test_super(struct super_block *sb, struct fs_context *fc) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct kernfs_super_info *sb_info = kernfs_info(sb); 29362306a36Sopenharmony_ci struct kernfs_super_info *info = fc->s_fs_info; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci return sb_info->root == info->root && sb_info->ns == info->ns; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cistatic int kernfs_set_super(struct super_block *sb, struct fs_context *fc) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct kernfs_fs_context *kfc = fc->fs_private; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci kfc->ns_tag = NULL; 30362306a36Sopenharmony_ci return set_anon_super_fc(sb, fc); 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci/** 30762306a36Sopenharmony_ci * kernfs_super_ns - determine the namespace tag of a kernfs super_block 30862306a36Sopenharmony_ci * @sb: super_block of interest 30962306a36Sopenharmony_ci * 31062306a36Sopenharmony_ci * Return: the namespace tag associated with kernfs super_block @sb. 31162306a36Sopenharmony_ci */ 31262306a36Sopenharmony_ciconst void *kernfs_super_ns(struct super_block *sb) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct kernfs_super_info *info = kernfs_info(sb); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return info->ns; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/** 32062306a36Sopenharmony_ci * kernfs_get_tree - kernfs filesystem access/retrieval helper 32162306a36Sopenharmony_ci * @fc: The filesystem context. 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * This is to be called from each kernfs user's fs_context->ops->get_tree() 32462306a36Sopenharmony_ci * implementation, which should set the specified ->@fs_type and ->@flags, and 32562306a36Sopenharmony_ci * specify the hierarchy and namespace tag to mount via ->@root and ->@ns, 32662306a36Sopenharmony_ci * respectively. 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci * Return: %0 on success, -errno on failure. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ciint kernfs_get_tree(struct fs_context *fc) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct kernfs_fs_context *kfc = fc->fs_private; 33362306a36Sopenharmony_ci struct super_block *sb; 33462306a36Sopenharmony_ci struct kernfs_super_info *info; 33562306a36Sopenharmony_ci int error; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci info = kzalloc(sizeof(*info), GFP_KERNEL); 33862306a36Sopenharmony_ci if (!info) 33962306a36Sopenharmony_ci return -ENOMEM; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci info->root = kfc->root; 34262306a36Sopenharmony_ci info->ns = kfc->ns_tag; 34362306a36Sopenharmony_ci INIT_LIST_HEAD(&info->node); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci fc->s_fs_info = info; 34662306a36Sopenharmony_ci sb = sget_fc(fc, kernfs_test_super, kernfs_set_super); 34762306a36Sopenharmony_ci if (IS_ERR(sb)) 34862306a36Sopenharmony_ci return PTR_ERR(sb); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci if (!sb->s_root) { 35162306a36Sopenharmony_ci struct kernfs_super_info *info = kernfs_info(sb); 35262306a36Sopenharmony_ci struct kernfs_root *root = kfc->root; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci kfc->new_sb_created = true; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci error = kernfs_fill_super(sb, kfc); 35762306a36Sopenharmony_ci if (error) { 35862306a36Sopenharmony_ci deactivate_locked_super(sb); 35962306a36Sopenharmony_ci return error; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci sb->s_flags |= SB_ACTIVE; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci uuid_gen(&sb->s_uuid); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci down_write(&root->kernfs_supers_rwsem); 36662306a36Sopenharmony_ci list_add(&info->node, &info->root->supers); 36762306a36Sopenharmony_ci up_write(&root->kernfs_supers_rwsem); 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci fc->root = dget(sb->s_root); 37162306a36Sopenharmony_ci return 0; 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_civoid kernfs_free_fs_context(struct fs_context *fc) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci /* Note that we don't deal with kfc->ns_tag here. */ 37762306a36Sopenharmony_ci kfree(fc->s_fs_info); 37862306a36Sopenharmony_ci fc->s_fs_info = NULL; 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci/** 38262306a36Sopenharmony_ci * kernfs_kill_sb - kill_sb for kernfs 38362306a36Sopenharmony_ci * @sb: super_block being killed 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * This can be used directly for file_system_type->kill_sb(). If a kernfs 38662306a36Sopenharmony_ci * user needs extra cleanup, it can implement its own kill_sb() and call 38762306a36Sopenharmony_ci * this function at the end. 38862306a36Sopenharmony_ci */ 38962306a36Sopenharmony_civoid kernfs_kill_sb(struct super_block *sb) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci struct kernfs_super_info *info = kernfs_info(sb); 39262306a36Sopenharmony_ci struct kernfs_root *root = info->root; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci down_write(&root->kernfs_supers_rwsem); 39562306a36Sopenharmony_ci list_del(&info->node); 39662306a36Sopenharmony_ci up_write(&root->kernfs_supers_rwsem); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* 39962306a36Sopenharmony_ci * Remove the superblock from fs_supers/s_instances 40062306a36Sopenharmony_ci * so we can't find it, before freeing kernfs_super_info. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_ci kill_anon_super(sb); 40362306a36Sopenharmony_ci kfree(info); 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic void __init kernfs_mutex_init(void) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci int count; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci for (count = 0; count < NR_KERNFS_LOCKS; count++) 41162306a36Sopenharmony_ci mutex_init(&kernfs_locks->open_file_mutex[count]); 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic void __init kernfs_lock_init(void) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci kernfs_locks = kmalloc(sizeof(struct kernfs_global_locks), GFP_KERNEL); 41762306a36Sopenharmony_ci WARN_ON(!kernfs_locks); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci kernfs_mutex_init(); 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_civoid __init kernfs_init(void) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci kernfs_node_cache = kmem_cache_create("kernfs_node_cache", 42562306a36Sopenharmony_ci sizeof(struct kernfs_node), 42662306a36Sopenharmony_ci 0, SLAB_PANIC, NULL); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* Creates slab cache for kernfs inode attributes */ 42962306a36Sopenharmony_ci kernfs_iattrs_cache = kmem_cache_create("kernfs_iattrs_cache", 43062306a36Sopenharmony_ci sizeof(struct kernfs_iattrs), 43162306a36Sopenharmony_ci 0, SLAB_PANIC, NULL); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci kernfs_lock_init(); 43462306a36Sopenharmony_ci} 435