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

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

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
Loading
Loading
Loading
Loading
+36 −26
Original line number Diff line number Diff line
@@ -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 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure)
		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 */
}

/*