|
@@ -438,7 +438,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
|
|
|
{
|
|
|
list_del(&dentry->d_u.d_child);
|
|
|
/*
|
|
|
- * Inform try_to_ascend() that we are no longer attached to the
|
|
|
+ * Inform d_walk() that we are no longer attached to the
|
|
|
* dentry tree
|
|
|
*/
|
|
|
dentry->d_flags |= DCACHE_DENTRY_KILLED;
|
|
@@ -1038,34 +1038,6 @@ void shrink_dcache_sb(struct super_block *sb)
|
|
|
}
|
|
|
EXPORT_SYMBOL(shrink_dcache_sb);
|
|
|
|
|
|
-/*
|
|
|
- * This tries to ascend one level of parenthood, but
|
|
|
- * we can race with renaming, so we need to re-check
|
|
|
- * the parenthood after dropping the lock and check
|
|
|
- * that the sequence number still matches.
|
|
|
- */
|
|
|
-static struct dentry *try_to_ascend(struct dentry *old, unsigned seq)
|
|
|
-{
|
|
|
- struct dentry *new = old->d_parent;
|
|
|
-
|
|
|
- rcu_read_lock();
|
|
|
- spin_unlock(&old->d_lock);
|
|
|
- spin_lock(&new->d_lock);
|
|
|
-
|
|
|
- /*
|
|
|
- * might go back up the wrong parent if we have had a rename
|
|
|
- * or deletion
|
|
|
- */
|
|
|
- if (new != old->d_parent ||
|
|
|
- (old->d_flags & DCACHE_DENTRY_KILLED) ||
|
|
|
- need_seqretry(&rename_lock, seq)) {
|
|
|
- spin_unlock(&new->d_lock);
|
|
|
- new = NULL;
|
|
|
- }
|
|
|
- rcu_read_unlock();
|
|
|
- return new;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* enum d_walk_ret - action to talke during tree walk
|
|
|
* @D_WALK_CONTINUE: contrinue walk
|
|
@@ -1154,9 +1126,24 @@ resume:
|
|
|
*/
|
|
|
if (this_parent != parent) {
|
|
|
struct dentry *child = this_parent;
|
|
|
- this_parent = try_to_ascend(this_parent, seq);
|
|
|
- if (!this_parent)
|
|
|
+ this_parent = child->d_parent;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ spin_unlock(&child->d_lock);
|
|
|
+ spin_lock(&this_parent->d_lock);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * might go back up the wrong parent if we have had a rename
|
|
|
+ * or deletion
|
|
|
+ */
|
|
|
+ if (this_parent != child->d_parent ||
|
|
|
+ (child->d_flags & DCACHE_DENTRY_KILLED) ||
|
|
|
+ need_seqretry(&rename_lock, seq)) {
|
|
|
+ spin_unlock(&this_parent->d_lock);
|
|
|
+ rcu_read_unlock();
|
|
|
goto rename_retry;
|
|
|
+ }
|
|
|
+ rcu_read_unlock();
|
|
|
next = child->d_u.d_child.next;
|
|
|
goto resume;
|
|
|
}
|