kernfs: define kernfs_node_dentry
Add a new kernfs api is added to lookup the dentry for a particular kernfs path. Signed-off-by: Aditya Kali <adityakali@google.com> Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
a0530e087e
commit
fb3c831565
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/magic.h>
|
#include <linux/magic.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/namei.h>
|
||||||
|
|
||||||
#include "kernfs-internal.h"
|
#include "kernfs-internal.h"
|
||||||
|
|
||||||
|
@ -62,6 +63,74 @@ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
|
||||||
return NULL;
|
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.
|
||||||
|
*/
|
||||||
|
static struct 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 (child->parent != parent) {
|
||||||
|
if (!child->parent)
|
||||||
|
return NULL;
|
||||||
|
child = child->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
|
||||||
|
struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct dentry *dentry;
|
||||||
|
struct kernfs_node *knparent = NULL;
|
||||||
|
|
||||||
|
BUG_ON(sb->s_op != &kernfs_sops);
|
||||||
|
|
||||||
|
dentry = dget(sb->s_root);
|
||||||
|
|
||||||
|
/* Check if this is the root kernfs_node */
|
||||||
|
if (!kn->parent)
|
||||||
|
return dentry;
|
||||||
|
|
||||||
|
knparent = find_next_ancestor(kn, NULL);
|
||||||
|
if (WARN_ON(!knparent))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
do {
|
||||||
|
struct dentry *dtmp;
|
||||||
|
struct kernfs_node *kntmp;
|
||||||
|
|
||||||
|
if (kn == knparent)
|
||||||
|
return dentry;
|
||||||
|
kntmp = find_next_ancestor(kn, knparent);
|
||||||
|
if (WARN_ON(!kntmp))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
mutex_lock(&d_inode(dentry)->i_mutex);
|
||||||
|
dtmp = lookup_one_len(kntmp->name, dentry, strlen(kntmp->name));
|
||||||
|
mutex_unlock(&d_inode(dentry)->i_mutex);
|
||||||
|
dput(dentry);
|
||||||
|
if (IS_ERR(dtmp))
|
||||||
|
return dtmp;
|
||||||
|
knparent = kntmp;
|
||||||
|
dentry = dtmp;
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
||||||
{
|
{
|
||||||
struct kernfs_super_info *info = kernfs_info(sb);
|
struct kernfs_super_info *info = kernfs_info(sb);
|
||||||
|
|
|
@ -284,6 +284,8 @@ struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry);
|
||||||
struct kernfs_root *kernfs_root_from_sb(struct super_block *sb);
|
struct kernfs_root *kernfs_root_from_sb(struct super_block *sb);
|
||||||
struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn);
|
struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn);
|
||||||
|
|
||||||
|
struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
|
||||||
|
struct super_block *sb);
|
||||||
struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
|
struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
|
||||||
unsigned int flags, void *priv);
|
unsigned int flags, void *priv);
|
||||||
void kernfs_destroy_root(struct kernfs_root *root);
|
void kernfs_destroy_root(struct kernfs_root *root);
|
||||||
|
|
Loading…
Reference in New Issue