aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs/kernfs-internal.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-01-17 09:58:25 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-17 14:50:07 -0500
commitdb4aad209bc9aefd91f0a9aeb9e37364088b39ad (patch)
tree28cc941640469a11111808a6e77be61e892e5041 /fs/kernfs/kernfs-internal.h
parent917f56caaabc215f9658006dad28a9665ec0ce19 (diff)
kernfs: associate a new kernfs_node with its parent on creation
Once created, a kernfs_node is always destroyed by kernfs_put(). Since ba7443bc656e ("sysfs, kernfs: implement kernfs_create/destroy_root()"), kernfs_put() depends on kernfs_root() to locate the ino_ida. kernfs_root() in turn depends on kernfs_node->parent being set for !dir nodes. This means that kernfs_put() of a !dir node requires its ->parent to be initialized. This leads to oops when a newly created !dir node is destroyed without going through kernfs_add_one() or after failing kernfs_add_one() before ->parent is set. kernfs_root() invoked from kernfs_put() will try to dereference NULL parent. Fix it by moving parent association to kernfs_new_node() from kernfs_add_one(). kernfs_new_node() now takes @parent instead of @root and determines the root from the parent and also sets the new node's parent properly. @parent parameter is removed from kernfs_add_one(). As there's no parent when creating the root node, __kernfs_new_node() which takes @root as before and doesn't set the parent is used in that case. This ensures that a kernfs_node in any stage in its life has its parent associated and thus can be put. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/kernfs/kernfs-internal.h')
-rw-r--r--fs/kernfs/kernfs-internal.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index c6ba5bc37a98..eb536b76374a 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -101,11 +101,11 @@ extern const struct inode_operations kernfs_dir_iops;
101struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); 101struct kernfs_node *kernfs_get_active(struct kernfs_node *kn);
102void kernfs_put_active(struct kernfs_node *kn); 102void kernfs_put_active(struct kernfs_node *kn);
103void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); 103void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt);
104int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, 104int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn);
105 struct kernfs_node *parent);
106void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); 105void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt);
107struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, 106struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
108 umode_t mode, unsigned flags); 107 const char *name, umode_t mode,
108 unsigned flags);
109 109
110/* 110/*
111 * file.c 111 * file.c