Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f657a666 authored by Al Viro's avatar Al Viro
Browse files

get rid of trylock loop around dentry_kill()



In case when trylock in there fails, deal with it directly in
dentry_kill().  Note that in cases when we drop and retake
->d_lock, we need to recheck whether to retain the dentry.
Another thing is that dropping/retaking ->d_lock might have
ended up with negative dentry turning into positive; that,
of course, can happen only once...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 62d9956c
Loading
Loading
Loading
Loading
+27 −7
Original line number Diff line number Diff line
@@ -651,23 +651,43 @@ static struct dentry *dentry_kill(struct dentry *dentry)
	struct dentry *parent = NULL;

	if (inode && unlikely(!spin_trylock(&inode->i_lock)))
		goto failed;
		goto slow_positive;

	if (!IS_ROOT(dentry)) {
		parent = dentry->d_parent;
		if (unlikely(!spin_trylock(&parent->d_lock))) {
			if (inode)
				spin_unlock(&inode->i_lock);
			goto failed;
			parent = __lock_parent(dentry);
			if (likely(inode || !dentry->d_inode))
				goto got_locks;
			/* negative that became positive */
			if (parent)
				spin_unlock(&parent->d_lock);
			inode = dentry->d_inode;
			goto slow_positive;
		}
	}

	__dentry_kill(dentry);
	return parent;

failed:
slow_positive:
	spin_unlock(&dentry->d_lock);
	return dentry; /* try again with same dentry */
	spin_lock(&inode->i_lock);
	spin_lock(&dentry->d_lock);
	parent = lock_parent(dentry);
got_locks:
	if (unlikely(dentry->d_lockref.count != 1)) {
		dentry->d_lockref.count--;
	} else if (likely(!retain_dentry(dentry))) {
		__dentry_kill(dentry);
		return parent;
	}
	/* we are keeping it, after all */
	if (inode)
		spin_unlock(&inode->i_lock);
	if (parent)
		spin_unlock(&parent->d_lock);
	spin_unlock(&dentry->d_lock);
	return NULL;
}

/*