Skip to content

Commit

Permalink
dcache.c: create helper function for duplicated functionality
Browse files Browse the repository at this point in the history
This creates a helper function for he "try to ascend into the parent
directory" case, which was written out in triplicate before.  With all
the locking and subtle sequence number stuff, we really don't want to
duplicate that kind of code.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Linus Torvalds committed Mar 15, 2011
1 parent 76ca078 commit c826cb7
Showing 1 changed file with 37 additions and 51 deletions.
88 changes: 37 additions & 51 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,34 @@ void shrink_dcache_for_umount(struct super_block *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, int locked, 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 ||
(!locked && read_seqretry(&rename_lock, seq))) {
spin_unlock(&new->d_lock);
new = NULL;
}
rcu_read_unlock();
return new;
}


/*
* Search for at least 1 mount point in the dentry's subdirs.
* We descend to the next level whenever the d_subdirs
Expand Down Expand Up @@ -1066,24 +1094,10 @@ int have_submounts(struct dentry *parent)
* All done at this level ... ascend and resume the search.
*/
if (this_parent != parent) {
struct dentry *tmp;
struct dentry *child;

tmp = this_parent->d_parent;
rcu_read_lock();
spin_unlock(&this_parent->d_lock);
child = this_parent;
this_parent = tmp;
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 ||
(!locked && read_seqretry(&rename_lock, seq))) {
spin_unlock(&this_parent->d_lock);
rcu_read_unlock();
struct dentry *child = this_parent;
this_parent = try_to_ascend(this_parent, locked, seq);
if (!this_parent)
goto rename_retry;
}
rcu_read_unlock();
next = child->d_u.d_child.next;
goto resume;
}
Expand Down Expand Up @@ -1181,24 +1195,10 @@ static int select_parent(struct dentry * parent)
* All done at this level ... ascend and resume the search.
*/
if (this_parent != parent) {
struct dentry *tmp;
struct dentry *child;

tmp = this_parent->d_parent;
rcu_read_lock();
spin_unlock(&this_parent->d_lock);
child = this_parent;
this_parent = tmp;
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 ||
(!locked && read_seqretry(&rename_lock, seq))) {
spin_unlock(&this_parent->d_lock);
rcu_read_unlock();
struct dentry *child = this_parent;
this_parent = try_to_ascend(this_parent, locked, seq);
if (!this_parent)
goto rename_retry;
}
rcu_read_unlock();
next = child->d_u.d_child.next;
goto resume;
}
Expand Down Expand Up @@ -2942,28 +2942,14 @@ void d_genocide(struct dentry *root)
spin_unlock(&dentry->d_lock);
}
if (this_parent != root) {
struct dentry *tmp;
struct dentry *child;

tmp = this_parent->d_parent;
struct dentry *child = this_parent;
if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
this_parent->d_flags |= DCACHE_GENOCIDE;
this_parent->d_count--;
}
rcu_read_lock();
spin_unlock(&this_parent->d_lock);
child = this_parent;
this_parent = tmp;
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 ||
(!locked && read_seqretry(&rename_lock, seq))) {
spin_unlock(&this_parent->d_lock);
rcu_read_unlock();
this_parent = try_to_ascend(this_parent, locked, seq);
if (!this_parent)
goto rename_retry;
}
rcu_read_unlock();
next = child->d_u.d_child.next;
goto resume;
}
Expand Down

0 comments on commit c826cb7

Please sign in to comment.