mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-01 11:54:10 +00:00
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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
d36a1dd9f7
commit
bca585d24a
2 changed files with 27 additions and 0 deletions
25
fs/dcache.c
25
fs/dcache.c
|
@ -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 *);
|
||||||
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 *);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue