Commit e55fd011 authored by Al Viro's avatar Al Viro

split dentry_kill()

... into trylocks and everything else.  The latter (actual killing)
is __dentry_kill().
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 64fd72e0
...@@ -441,36 +441,12 @@ void d_drop(struct dentry *dentry) ...@@ -441,36 +441,12 @@ void d_drop(struct dentry *dentry)
} }
EXPORT_SYMBOL(d_drop); EXPORT_SYMBOL(d_drop);
/* static void __dentry_kill(struct dentry *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;
struct dentry *parent = NULL; struct dentry *parent = NULL;
bool can_free = true; 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)) if (!IS_ROOT(dentry))
parent = dentry->d_parent; 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. * The dentry is now unrecoverably dead to the world.
...@@ -514,10 +490,44 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure) ...@@ -514,10 +490,44 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure)
can_free = false; can_free = false;
} }
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
out:
if (likely(can_free)) if (likely(can_free))
dentry_free(dentry); 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; return parent;
failed:
if (unlock_on_failure) {
spin_unlock(&dentry->d_lock);
cpu_relax();
}
return dentry; /* try again with same dentry */
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment