 fs/dcache.c | 17 ++++++++++-------
 fs/namei.c  | 23 +++++------------------
 2 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 761e31bacbc2..ab34bfc4d199 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -229,7 +229,7 @@ static void __d_free(struct rcu_head *head)
  */
 static void d_free(struct dentry *dentry)
 {
-	BUG_ON(dentry->d_lockref.count);
+	BUG_ON((int)dentry->d_lockref.count > 0);
 	this_cpu_dec(nr_dentry);
 	if (dentry->d_op && dentry->d_op->d_release)
 		dentry->d_op->d_release(dentry);
@@ -443,7 +443,7 @@ EXPORT_SYMBOL(d_drop);
  * If ref is non-zero, then decrement the refcount too.
  * Returns dentry requiring refcount drop, or NULL if we're done.
  */
-static inline struct dentry *dentry_kill(struct dentry *dentry, int ref)
+static inline struct dentry *dentry_kill(struct dentry *dentry)
 	__releases(dentry->d_lock)
 {
 	struct inode *inode;
@@ -466,8 +466,11 @@ relock:
 		goto relock;
 	}
 
-	if (ref)
-		dentry->d_lockref.count--;
+	/*
+	 * The dentry is now unrecoverably dead to the world.
+	 */
+	lockref_mark_dead(&dentry->d_lockref);
+
 	/*
 	 * inform the fs via d_prune that this dentry is about to be
 	 * unhashed and destroyed.
@@ -535,7 +538,7 @@ repeat:
 	return;
 
 kill_it:
-	dentry = dentry_kill(dentry, 1);
+	dentry = dentry_kill(dentry);
 	if (dentry)
 		goto repeat;
 }
@@ -760,7 +763,7 @@ static void try_prune_one_dentry(struct dentry *dentry)
 {
 	struct dentry *parent;
 
-	parent = dentry_kill(dentry, 0);
+	parent = dentry_kill(dentry);
 	/*
 	 * If dentry_kill returns NULL, we have nothing more to do.
 	 * if it returns the same dentry, trylocks failed. In either
@@ -781,7 +784,7 @@ static void try_prune_one_dentry(struct dentry *dentry)
 	while (dentry) {
 		if (lockref_put_or_lock(&dentry->d_lockref))
 			return;
-		dentry = dentry_kill(dentry, 1);
+		dentry = dentry_kill(dentry);
 	}
 }
 
diff --git a/fs/namei.c b/fs/namei.c
index f415c6683a83..cc4bcfaa8624 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -517,25 +517,12 @@ static inline void unlock_rcu_walk(void)
  */
 static inline int d_rcu_to_refcount(struct dentry *dentry, seqcount_t *validate, unsigned seq)
 {
-	int gotref;
-
-	gotref = lockref_get_or_lock(&dentry->d_lockref);
-
-	/* Does the sequence number still match? */
-	if (read_seqcount_retry(validate, seq)) {
-		if (gotref)
-			dput(dentry);
-		else
-			spin_unlock(&dentry->d_lock);
-		return -ECHILD;
-	}
-
-	/* Get the ref now, if we couldn't get it originally */
-	if (!gotref) {
-		dentry->d_lockref.count++;
-		spin_unlock(&dentry->d_lock);
+	if (likely(lockref_get_not_dead(&dentry->d_lockref))) {
+		if (!read_seqcount_retry(validate, seq))
+				return 0;
+		dput(dentry);
 	}
-	return 0;
+	return -ECHILD;
 }
 
 /**
