Skip to content
Snippets Groups Projects
Commit bca585d2 authored by Al Viro's avatar Al Viro
Browse files

new helper: d_find_alias_rcu()


similar to d_find_alias(inode), except that
	* the caller must be holding rcu_read_lock()
	* inode must not be freed until matching rcu_read_unlock()
	* result is *NOT* pinned and can only be dereferenced until
the matching rcu_read_unlock().

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent d36a1dd9
No related branches found
No related tags found
No related merge requests found
...@@ -1042,6 +1042,31 @@ struct dentry *d_find_alias(struct inode *inode) ...@@ -1042,6 +1042,31 @@ struct dentry *d_find_alias(struct inode *inode)
} }
EXPORT_SYMBOL(d_find_alias); EXPORT_SYMBOL(d_find_alias);
/*
* Caller MUST be holding rcu_read_lock() and be guaranteed
* that inode won't get freed until rcu_read_unlock().
*/
struct dentry *d_find_alias_rcu(struct inode *inode)
{
struct hlist_head *l = &inode->i_dentry;
struct dentry *de = NULL;
spin_lock(&inode->i_lock);
// ->i_dentry and ->i_rcu are colocated, but the latter won't be
// used without having I_FREEING set, which means no aliases left
if (likely(!(inode->i_state & I_FREEING) && !hlist_empty(l))) {
if (S_ISDIR(inode->i_mode)) {
de = hlist_entry(l->first, struct dentry, d_u.d_alias);
} else {
hlist_for_each_entry(de, l, d_u.d_alias)
if (!d_unhashed(de))
break;
}
}
spin_unlock(&inode->i_lock);
return de;
}
/* /*
* Try to kill dentries associated with this inode. * Try to kill dentries associated with this inode.
* WARNING: you must own a reference to inode. * WARNING: you must own a reference to inode.
......
...@@ -262,6 +262,8 @@ extern void d_tmpfile(struct dentry *, struct inode *); ...@@ -262,6 +262,8 @@ extern void d_tmpfile(struct dentry *, struct inode *);
extern struct dentry *d_find_alias(struct inode *); extern struct dentry *d_find_alias(struct inode *);
extern void d_prune_aliases(struct inode *); extern void d_prune_aliases(struct inode *);
extern struct dentry *d_find_alias_rcu(struct inode *);
/* test whether we have any submounts in a subdir tree */ /* test whether we have any submounts in a subdir tree */
extern int path_has_submounts(const struct path *); extern int path_has_submounts(const struct path *);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment