... into trylocks and everything else.  The latter (actual killing)
is __dentry_kill().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2014-05-28 13:51:12 -04:00
Родитель 64fd72e0a4
Коммит e55fd01154
1 изменённых файлов: 36 добавлений и 26 удалений

Просмотреть файл

@ -441,36 +441,12 @@ void d_drop(struct dentry *dentry)
}
EXPORT_SYMBOL(d_drop);
/*
* Finish off a dentry we've decided to kill.
* dentry->d_lock must be held, returns with it unlocked.
* If ref is non-zero, then decrement the refcount too.
* Returns dentry requiring refcount drop, or NULL if we're done.
*/
static struct dentry *
dentry_kill(struct dentry *dentry, int unlock_on_failure)
__releases(dentry->d_lock)
static void __dentry_kill(struct dentry *dentry)
{
struct inode *inode;
struct dentry *parent = NULL;
bool can_free = true;
inode = dentry->d_inode;
if (inode && !spin_trylock(&inode->i_lock)) {
relock:
if (unlock_on_failure) {
spin_unlock(&dentry->d_lock);
cpu_relax();
}
return dentry; /* try again with same dentry */
}
if (!IS_ROOT(dentry))
parent = dentry->d_parent;
if (parent && !spin_trylock(&parent->d_lock)) {
if (inode)
spin_unlock(&inode->i_lock);
goto relock;
}
/*
* The dentry is now unrecoverably dead to the world.
@ -514,10 +490,44 @@ relock:
can_free = false;
}
spin_unlock(&dentry->d_lock);
out:
if (likely(can_free))
dentry_free(dentry);
}
/*
* Finish off a dentry we've decided to kill.
* dentry->d_lock must be held, returns with it unlocked.
* If ref is non-zero, then decrement the refcount too.
* Returns dentry requiring refcount drop, or NULL if we're done.
*/
static struct dentry *
dentry_kill(struct dentry *dentry, int unlock_on_failure)
__releases(dentry->d_lock)
{
struct inode *inode = dentry->d_inode;
struct dentry *parent = NULL;
if (inode && unlikely(!spin_trylock(&inode->i_lock)))
goto failed;
if (!IS_ROOT(dentry)) {
parent = dentry->d_parent;
if (unlikely(!spin_trylock(&parent->d_lock))) {
if (inode)
spin_unlock(&inode->i_lock);
goto failed;
}
}
__dentry_kill(dentry);
return parent;
failed:
if (unlock_on_failure) {
spin_unlock(&dentry->d_lock);
cpu_relax();
}
return dentry; /* try again with same dentry */
}
/*