mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-22 06:32:08 +00:00
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>
This commit is contained in:
parent
0c23b2259a
commit
3eef34ad7d
3 changed files with 203 additions and 42 deletions
|
@ -91,7 +91,12 @@ struct kernfs_node {
|
|||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
struct lockdep_map dep_map;
|
||||
#endif
|
||||
/* the following two fields are published */
|
||||
/*
|
||||
* Use kernfs_get_parent() and kernfs_name/path() instead of
|
||||
* accessing the following two fields directly. If the node is
|
||||
* never moved to a different parent, it is safe to access the
|
||||
* parent directly.
|
||||
*/
|
||||
struct kernfs_node *parent;
|
||||
const char *name;
|
||||
|
||||
|
@ -229,6 +234,12 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
|
|||
return kn->flags & KERNFS_NS;
|
||||
}
|
||||
|
||||
int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
|
||||
char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
|
||||
size_t buflen);
|
||||
void pr_cont_kernfs_name(struct kernfs_node *kn);
|
||||
void pr_cont_kernfs_path(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
|
||||
const char *name, const void *ns);
|
||||
void kernfs_get(struct kernfs_node *kn);
|
||||
|
@ -283,6 +294,19 @@ static inline void kernfs_enable_ns(struct kernfs_node *kn) { }
|
|||
static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
|
||||
{ return false; }
|
||||
|
||||
static inline int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
|
||||
{ return -ENOSYS; }
|
||||
|
||||
static inline char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
|
||||
size_t buflen)
|
||||
{ return NULL; }
|
||||
|
||||
static inline void pr_cont_kernfs_name(struct kernfs_node *kn) { }
|
||||
static inline void pr_cont_kernfs_path(struct kernfs_node *kn) { }
|
||||
|
||||
static inline struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
|
||||
{ return NULL; }
|
||||
|
||||
static inline struct kernfs_node *
|
||||
kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
|
||||
const void *ns)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue