mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
configfs: dentry refcount needs to be pinned only once
currently we have a weird situation where
* symlinks and roots of subtrees created by mkdir are pinned once
* subdirectories of subtrees created by mkdir are pinned twice
* roots of subtrees created by register_{group,subsystem} are pinned
twice.
It makes things harder to follow for no good reason. The goal is to
encapsulate the unbalanced dget/dput into d_{make,discard}_persisitent()
and, preferably, allow a use of simple_recursive_removal() or analogue
thereof. So let's regularize that and pin things only once.
create_default_group() and configfs_register_subsystem() don't need to
keep their reference around on success - configfs_create_dir() has pinned
the sucker already. So we can drop the reference passed to
configfs_create_dir() (via configfs_attach_group(), etc.) both on success
and on failure. On the removal side we no longer have the double references,
so we need an explicit dget() to compensate.
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
abe91a2aa9
commit
1a29e25799
|
|
@ -657,7 +657,7 @@ static void detach_groups(struct dentry *dentry)
|
|||
if (!(sd->s_type & CONFIGFS_USET_DEFAULT))
|
||||
continue;
|
||||
|
||||
child = sd->s_dentry;
|
||||
child = dget(sd->s_dentry);
|
||||
spin_unlock(&configfs_dirent_lock);
|
||||
|
||||
inode_lock(d_inode(child));
|
||||
|
|
@ -708,8 +708,8 @@ static int create_default_group(struct config_group *parent_group,
|
|||
} else {
|
||||
BUG_ON(d_inode(child));
|
||||
d_drop(child);
|
||||
dput(child);
|
||||
}
|
||||
dput(child);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -1781,7 +1781,7 @@ EXPORT_SYMBOL(configfs_register_group);
|
|||
void configfs_unregister_group(struct config_group *group)
|
||||
{
|
||||
struct configfs_subsystem *subsys = group->cg_subsys;
|
||||
struct dentry *dentry = group->cg_item.ci_dentry;
|
||||
struct dentry *dentry = dget(group->cg_item.ci_dentry);
|
||||
struct dentry *parent = group->cg_item.ci_parent->ci_dentry;
|
||||
struct configfs_dirent *sd = dentry->d_fsdata;
|
||||
struct configfs_fragment *frag = sd->s_frag;
|
||||
|
|
@ -1896,12 +1896,12 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
|
|||
if (err) {
|
||||
BUG_ON(d_inode(dentry));
|
||||
d_drop(dentry);
|
||||
dput(dentry);
|
||||
} else {
|
||||
spin_lock(&configfs_dirent_lock);
|
||||
configfs_dir_set_ready(dentry->d_fsdata);
|
||||
spin_unlock(&configfs_dirent_lock);
|
||||
}
|
||||
dput(dentry);
|
||||
}
|
||||
|
||||
inode_unlock(d_inode(root));
|
||||
|
|
@ -1920,7 +1920,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
|
|||
void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
|
||||
{
|
||||
struct config_group *group = &subsys->su_group;
|
||||
struct dentry *dentry = group->cg_item.ci_dentry;
|
||||
struct dentry *dentry = dget(group->cg_item.ci_dentry);
|
||||
struct dentry *root = dentry->d_sb->s_root;
|
||||
struct configfs_dirent *sd = dentry->d_fsdata;
|
||||
struct configfs_fragment *frag = sd->s_frag;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user