diff options
author | Aditya Kali <adityakali@google.com> | 2016-01-29 03:54:08 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2016-02-16 13:04:58 -0500 |
commit | fb3c8315650f89a1993fb3ae3e74e9c7e4a1c9c0 (patch) | |
tree | 29772e52c73463ec3bd1f2c3b3c956ceaf143071 | |
parent | a0530e087e648263f81a81d62ca020f66b54bcb0 (diff) |
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>
-rw-r--r-- | fs/kernfs/mount.c | 69 | ||||
-rw-r--r-- | include/linux/kernfs.h | 2 |
2 files changed, 71 insertions, 0 deletions
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index 8eaf417187f1..b67dbccdaf88 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/magic.h> | 14 | #include <linux/magic.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/namei.h> | ||
17 | 18 | ||
18 | #include "kernfs-internal.h" | 19 | #include "kernfs-internal.h" |
19 | 20 | ||
@@ -62,6 +63,74 @@ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb) | |||
62 | return NULL; | 63 | return NULL; |
63 | } | 64 | } |
64 | 65 | ||
66 | /* | ||
67 | * find the next ancestor in the path down to @child, where @parent was the | ||
68 | * ancestor whose descendant we want to find. | ||
69 | * | ||
70 | * Say the path is /a/b/c/d. @child is d, @parent is NULL. We return the root | ||
71 | * node. If @parent is b, then we return the node for c. | ||
72 | * Passing in d as @parent is not ok. | ||
73 | */ | ||
74 | static struct kernfs_node *find_next_ancestor(struct kernfs_node *child, | ||
75 | struct kernfs_node *parent) | ||
76 | { | ||
77 | if (child == parent) { | ||
78 | pr_crit_once("BUG in find_next_ancestor: called with parent == child"); | ||
79 | return NULL; | ||
80 | } | ||
81 | |||
82 | while (child->parent != parent) { | ||
83 | if (!child->parent) | ||
84 | return NULL; | ||
85 | child = child->parent; | ||
86 | } | ||
87 | |||
88 | return child; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * kernfs_node_dentry - get a dentry for the given kernfs_node | ||
93 | * @kn: kernfs_node for which a dentry is needed | ||
94 | * @sb: the kernfs super_block | ||
95 | */ | ||
96 | struct dentry *kernfs_node_dentry(struct kernfs_node *kn, | ||
97 | struct super_block *sb) | ||
98 | { | ||
99 | struct dentry *dentry; | ||
100 | struct kernfs_node *knparent = NULL; | ||
101 | |||
102 | BUG_ON(sb->s_op != &kernfs_sops); | ||
103 | |||
104 | dentry = dget(sb->s_root); | ||
105 | |||
106 | /* Check if this is the root kernfs_node */ | ||
107 | if (!kn->parent) | ||
108 | return dentry; | ||
109 | |||
110 | knparent = find_next_ancestor(kn, NULL); | ||
111 | if (WARN_ON(!knparent)) | ||
112 | return ERR_PTR(-EINVAL); | ||
113 | |||
114 | do { | ||
115 | struct dentry *dtmp; | ||
116 | struct kernfs_node *kntmp; | ||
117 | |||
118 | if (kn == knparent) | ||
119 | return dentry; | ||
120 | kntmp = find_next_ancestor(kn, knparent); | ||
121 | if (WARN_ON(!kntmp)) | ||
122 | return ERR_PTR(-EINVAL); | ||
123 | mutex_lock(&d_inode(dentry)->i_mutex); | ||
124 | dtmp = lookup_one_len(kntmp->name, dentry, strlen(kntmp->name)); | ||
125 | mutex_unlock(&d_inode(dentry)->i_mutex); | ||
126 | dput(dentry); | ||
127 | if (IS_ERR(dtmp)) | ||
128 | return dtmp; | ||
129 | knparent = kntmp; | ||
130 | dentry = dtmp; | ||
131 | } while (true); | ||
132 | } | ||
133 | |||
65 | static int kernfs_fill_super(struct super_block *sb, unsigned long magic) | 134 | static int kernfs_fill_super(struct super_block *sb, unsigned long magic) |
66 | { | 135 | { |
67 | struct kernfs_super_info *info = kernfs_info(sb); | 136 | struct kernfs_super_info *info = kernfs_info(sb); |
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 716bfdede5f5..c06c44242f39 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h | |||
@@ -284,6 +284,8 @@ struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry); | |||
284 | struct kernfs_root *kernfs_root_from_sb(struct super_block *sb); | 284 | struct kernfs_root *kernfs_root_from_sb(struct super_block *sb); |
285 | struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn); | 285 | struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn); |
286 | 286 | ||
287 | struct dentry *kernfs_node_dentry(struct kernfs_node *kn, | ||
288 | struct super_block *sb); | ||
287 | struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, | 289 | struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, |
288 | unsigned int flags, void *priv); | 290 | unsigned int flags, void *priv); |
289 | void kernfs_destroy_root(struct kernfs_root *root); | 291 | void kernfs_destroy_root(struct kernfs_root *root); |