提交 fbc8d4c0 编写于 作者: N Nick Piggin

config fs: avoid switching ->d_op on live dentry

Switching d_op on a live dentry is racy in general, so avoid it. In this case
it is a negative dentry, which is safer, but there are still concurrent ops
which may be called on d_op in that case (eg. d_revalidate). So in general
a filesystem may not do this. Fix configfs so as not to do this.
Signed-off-by: NNick Piggin <npiggin@kernel.dk>
上级 5adcee1d
...@@ -232,10 +232,8 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd, ...@@ -232,10 +232,8 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd,
sd->s_mode = mode; sd->s_mode = mode;
sd->s_dentry = dentry; sd->s_dentry = dentry;
if (dentry) { if (dentry)
dentry->d_fsdata = configfs_get(sd); dentry->d_fsdata = configfs_get(sd);
dentry->d_op = &configfs_dentry_ops;
}
return 0; return 0;
} }
...@@ -278,7 +276,6 @@ static int create_dir(struct config_item * k, struct dentry * p, ...@@ -278,7 +276,6 @@ static int create_dir(struct config_item * k, struct dentry * p,
error = configfs_create(d, mode, init_dir); error = configfs_create(d, mode, init_dir);
if (!error) { if (!error) {
inc_nlink(p->d_inode); inc_nlink(p->d_inode);
(d)->d_op = &configfs_dentry_ops;
} else { } else {
struct configfs_dirent *sd = d->d_fsdata; struct configfs_dirent *sd = d->d_fsdata;
if (sd) { if (sd) {
...@@ -371,9 +368,7 @@ int configfs_create_link(struct configfs_symlink *sl, ...@@ -371,9 +368,7 @@ int configfs_create_link(struct configfs_symlink *sl,
CONFIGFS_ITEM_LINK); CONFIGFS_ITEM_LINK);
if (!err) { if (!err) {
err = configfs_create(dentry, mode, init_symlink); err = configfs_create(dentry, mode, init_symlink);
if (!err) if (err) {
dentry->d_op = &configfs_dentry_ops;
else {
struct configfs_dirent *sd = dentry->d_fsdata; struct configfs_dirent *sd = dentry->d_fsdata;
if (sd) { if (sd) {
spin_lock(&configfs_dirent_lock); spin_lock(&configfs_dirent_lock);
...@@ -493,7 +488,11 @@ static struct dentry * configfs_lookup(struct inode *dir, ...@@ -493,7 +488,11 @@ static struct dentry * configfs_lookup(struct inode *dir,
* If it doesn't exist and it isn't a NOT_PINNED item, * If it doesn't exist and it isn't a NOT_PINNED item,
* it must be negative. * it must be negative.
*/ */
return simple_lookup(dir, dentry, nd); if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
dentry->d_op = &configfs_dentry_ops;
d_add(dentry, NULL);
return NULL;
} }
out: out:
...@@ -685,6 +684,7 @@ static int create_default_group(struct config_group *parent_group, ...@@ -685,6 +684,7 @@ static int create_default_group(struct config_group *parent_group,
ret = -ENOMEM; ret = -ENOMEM;
child = d_alloc(parent, &name); child = d_alloc(parent, &name);
if (child) { if (child) {
child->d_op = &configfs_dentry_ops;
d_add(child, NULL); d_add(child, NULL);
ret = configfs_attach_group(&parent_group->cg_item, ret = configfs_attach_group(&parent_group->cg_item,
...@@ -1682,6 +1682,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) ...@@ -1682,6 +1682,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
err = -ENOMEM; err = -ENOMEM;
dentry = d_alloc(configfs_sb->s_root, &name); dentry = d_alloc(configfs_sb->s_root, &name);
if (dentry) { if (dentry) {
dentry->d_op = &configfs_dentry_ops;
d_add(dentry, NULL); d_add(dentry, NULL);
err = configfs_attach_group(sd->s_element, &group->cg_item, err = configfs_attach_group(sd->s_element, &group->cg_item,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册