/* * sysfs is built on top of kernfs and sysfs provides the power * management infrastructure to support suspend/hibernate by * writing to various files in /sys/power/. As filesystems may * be automatically frozen during suspend/hibernate implementing * freeze/thaw support for kernfs generically will cause * deadlocks as the suspending/hibernation initiating task will * hold a VFS lock that it will then wait upon to be released. * If freeze/thaw for kernfs is needed talk to the VFS.
*/
.freeze_fs = NULL,
.unfreeze_fs = NULL,
.freeze_super = NULL,
.thaw_super = NULL,
};
switch (fh_type) { case FILEID_KERNFS:
id = *(u64 *)fid; break; case FILEID_INO32_GEN: case FILEID_INO32_GEN_PARENT: /* * blk_log_action() exposes "LOW32,HIGH32" pair without * type and userland can call us with generic fid * constructed from them. Combine it back to ID. See * blk_log_action().
*/
id = ((u64)fid->i32.gen << 32) | fid->i32.ino; break; default: return NULL;
}
kn = kernfs_find_and_get_node_by_id(info->root, id); if (!kn) return ERR_PTR(-ESTALE);
/** * kernfs_root_from_sb - determine kernfs_root associated with a super_block * @sb: the super_block in question * * Return: the kernfs_root associated with @sb. If @sb is not a kernfs one, * %NULL is returned.
*/ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
{ if (sb->s_op == &kernfs_sops) return kernfs_info(sb)->root; return NULL;
}
/* * find the next ancestor in the path down to @child, where @parent was the * ancestor whose descendant we want to find. * * Say the path is /a/b/c/d. @child is d, @parent is %NULL. We return the root * node. If @parent is b, then we return the node for c. * Passing in d as @parent is not ok.
*/ staticstruct kernfs_node *find_next_ancestor(struct kernfs_node *child, struct kernfs_node *parent)
{ if (child == parent) {
pr_crit_once("BUG in find_next_ancestor: called with parent == child"); return NULL;
}
while (kernfs_parent(child) != parent) {
child = kernfs_parent(child); if (!child) return NULL;
}
return child;
}
/** * kernfs_node_dentry - get a dentry for the given kernfs_node * @kn: kernfs_node for which a dentry is needed * @sb: the kernfs super_block * * Return: the dentry pointer
*/ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, struct super_block *sb)
{ struct dentry *dentry; struct kernfs_node *knparent; struct kernfs_root *root;
BUG_ON(sb->s_op != &kernfs_sops);
dentry = dget(sb->s_root);
/* Check if this is the root kernfs_node */ if (!rcu_access_pointer(kn->__parent)) return dentry;
root = kernfs_root(kn); /* * As long as kn is valid, its parent can not vanish. This is cgroup's * kn so it can't have its parent replaced. Therefore it is safe to use * the ancestor node outside of the RCU or locked section.
*/ if (WARN_ON_ONCE(!(root->flags & KERNFS_ROOT_INVARIANT_PARENT))) return ERR_PTR(-EINVAL);
scoped_guard(rcu) {
knparent = find_next_ancestor(kn, NULL);
} if (WARN_ON(!knparent)) {
dput(dentry); return ERR_PTR(-EINVAL);
}
do { struct dentry *dtmp; struct kernfs_node *kntmp; constchar *name;
if (kn == knparent) return dentry;
scoped_guard(rwsem_read, &root->kernfs_rwsem) {
kntmp = find_next_ancestor(kn, knparent); if (WARN_ON(!kntmp)) {
dput(dentry); return ERR_PTR(-EINVAL);
}
name = kstrdup(kernfs_rcu_name(kntmp), GFP_KERNEL);
} if (!name) {
dput(dentry); return ERR_PTR(-ENOMEM);
}
dtmp = lookup_noperm_positive_unlocked(&QSTR(name), dentry);
dput(dentry);
kfree(name); if (IS_ERR(dtmp)) return dtmp;
knparent = kntmp;
dentry = dtmp;
} while (true);
}
info->sb = sb; /* Userspace would break if executables or devices appear on sysfs */
sb->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = kfc->magic;
sb->s_op = &kernfs_sops;
sb->s_xattr = kernfs_xattr_handlers; if (info->root->flags & KERNFS_ROOT_SUPPORT_EXPORTOP)
sb->s_export_op = &kernfs_export_ops;
sb->s_time_gran = 1;
/* sysfs dentries and inodes don't require IO to create */
sb->s_shrink->seeks = 0;
/* get root inode, initialize and unlock it */
down_read(&kf_root->kernfs_rwsem);
inode = kernfs_get_inode(sb, info->root->kn);
up_read(&kf_root->kernfs_rwsem); if (!inode) {
pr_debug("kernfs: could not get root inode\n"); return -ENOMEM;
}
/* instantiate and link root dentry */
root = d_make_root(inode); if (!root) {
pr_debug("%s: could not get root dentry!\n", __func__); return -ENOMEM;
}
sb->s_root = root;
set_default_d_op(sb, &kernfs_dops); return 0;
}
/** * kernfs_super_ns - determine the namespace tag of a kernfs super_block * @sb: super_block of interest * * Return: the namespace tag associated with kernfs super_block @sb.
*/ constvoid *kernfs_super_ns(struct super_block *sb)
{ struct kernfs_super_info *info = kernfs_info(sb);
return info->ns;
}
/** * kernfs_get_tree - kernfs filesystem access/retrieval helper * @fc: The filesystem context. * * This is to be called from each kernfs user's fs_context->ops->get_tree() * implementation, which should set the specified ->@fs_type and ->@flags, and * specify the hierarchy and namespace tag to mount via ->@root and ->@ns, * respectively. * * Return: %0 on success, -errno on failure.
*/ int kernfs_get_tree(struct fs_context *fc)
{ struct kernfs_fs_context *kfc = fc->fs_private; struct super_block *sb; struct kernfs_super_info *info; int error;
info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM;
void kernfs_free_fs_context(struct fs_context *fc)
{ /* Note that we don't deal with kfc->ns_tag here. */
kfree(fc->s_fs_info);
fc->s_fs_info = NULL;
}
/** * kernfs_kill_sb - kill_sb for kernfs * @sb: super_block being killed * * This can be used directly for file_system_type->kill_sb(). If a kernfs * user needs extra cleanup, it can implement its own kill_sb() and call * this function at the end.
*/ void kernfs_kill_sb(struct super_block *sb)
{ struct kernfs_super_info *info = kernfs_info(sb); struct kernfs_root *root = info->root;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.