aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/kernfs.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-02-07 13:32:07 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-07 19:05:35 -0500
commit3eef34ad7dc369b7183ec383908aff3da2f6e5ec (patch)
treefac6ef1dd497adeff55fae499d953d5d51061867 /include/linux/kernfs.h
parent0c23b2259a4850494e2c53e864ea840597c6cdd3 (diff)
kernfs: implement kernfs_get_parent(), kernfs_name/path() and friends
kernfs_node->parent and ->name are currently marked as "published" indicating that kernfs users may access them directly; however, those fields may get updated by kernfs_rename[_ns]() and unrestricted access may lead to erroneous values or oops. Protect ->parent and ->name updates with a irq-safe spinlock kernfs_rename_lock and implement the following accessors for these fields. * kernfs_name() - format the node's name into the specified buffer * kernfs_path() - format the node's path into the specified buffer * pr_cont_kernfs_name() - pr_cont a node's name (doesn't need buffer) * pr_cont_kernfs_path() - pr_cont a node's path (doesn't need buffer) * kernfs_get_parent() - pin and return a node's parent All can be called under any context. The recursive sysfs_pathname() in fs/sysfs/dir.c is replaced with kernfs_path() and sysfs_rename_dir_ns() is updated to use kernfs_get_parent() instead of dereferencing parent directly. v2: Dummy definition of kernfs_path() for !CONFIG_KERNFS was missing static inline making it cause a lot of build warnings. Add it. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/kernfs.h')
-rw-r--r--include/linux/kernfs.h26
1 files changed, 25 insertions, 1 deletions
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 9c899040c05e..8736ee86a1d6 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -91,7 +91,12 @@ struct kernfs_node {
91#ifdef CONFIG_DEBUG_LOCK_ALLOC 91#ifdef CONFIG_DEBUG_LOCK_ALLOC
92 struct lockdep_map dep_map; 92 struct lockdep_map dep_map;
93#endif 93#endif
94 /* the following two fields are published */ 94 /*
95 * Use kernfs_get_parent() and kernfs_name/path() instead of
96 * accessing the following two fields directly. If the node is
97 * never moved to a different parent, it is safe to access the
98 * parent directly.
99 */
95 struct kernfs_node *parent; 100 struct kernfs_node *parent;
96 const char *name; 101 const char *name;
97 102
@@ -229,6 +234,12 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
229 return kn->flags & KERNFS_NS; 234 return kn->flags & KERNFS_NS;
230} 235}
231 236
237int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
238char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
239 size_t buflen);
240void pr_cont_kernfs_name(struct kernfs_node *kn);
241void pr_cont_kernfs_path(struct kernfs_node *kn);
242struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn);
232struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, 243struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
233 const char *name, const void *ns); 244 const char *name, const void *ns);
234void kernfs_get(struct kernfs_node *kn); 245void kernfs_get(struct kernfs_node *kn);
@@ -283,6 +294,19 @@ static inline void kernfs_enable_ns(struct kernfs_node *kn) { }
283static inline bool kernfs_ns_enabled(struct kernfs_node *kn) 294static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
284{ return false; } 295{ return false; }
285 296
297static inline int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
298{ return -ENOSYS; }
299
300static inline char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
301 size_t buflen)
302{ return NULL; }
303
304static inline void pr_cont_kernfs_name(struct kernfs_node *kn) { }
305static inline void pr_cont_kernfs_path(struct kernfs_node *kn) { }
306
307static inline struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
308{ return NULL; }
309
286static inline struct kernfs_node * 310static inline struct kernfs_node *
287kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, 311kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
288 const void *ns) 312 const void *ns)