diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-25 17:04:27 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-15 22:04:17 -0500 |
commit | 31dec1327e377b6d91a8a6c92b5cd8513939a233 (patch) | |
tree | 575b1aa7e37ab0fd8b00c9b756d107232e5aca7e /fs/dcache.c | |
parent | 482db9066199813d6b999b65a3171afdbec040b6 (diff) |
fold try_to_ascend() into the sole remaining caller
There used to be a bunch of tree-walkers in dcache.c, all alike.
try_to_ascend() had been introduced to abstract a piece of logics
duplicated in all of them. These days all these tree-walkers are
implemented via the same iterator (d_walk()), which is the only
remaining caller of try_to_ascend(), so let's fold it back...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 49 |
1 files changed, 18 insertions, 31 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 7f079d00475a..4bdb300b16e2 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -438,7 +438,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
438 | { | 438 | { |
439 | list_del(&dentry->d_u.d_child); | 439 | list_del(&dentry->d_u.d_child); |
440 | /* | 440 | /* |
441 | * Inform try_to_ascend() that we are no longer attached to the | 441 | * Inform d_walk() that we are no longer attached to the |
442 | * dentry tree | 442 | * dentry tree |
443 | */ | 443 | */ |
444 | dentry->d_flags |= DCACHE_DENTRY_KILLED; | 444 | dentry->d_flags |= DCACHE_DENTRY_KILLED; |
@@ -1038,34 +1038,6 @@ void shrink_dcache_sb(struct super_block *sb) | |||
1038 | } | 1038 | } |
1039 | EXPORT_SYMBOL(shrink_dcache_sb); | 1039 | EXPORT_SYMBOL(shrink_dcache_sb); |
1040 | 1040 | ||
1041 | /* | ||
1042 | * This tries to ascend one level of parenthood, but | ||
1043 | * we can race with renaming, so we need to re-check | ||
1044 | * the parenthood after dropping the lock and check | ||
1045 | * that the sequence number still matches. | ||
1046 | */ | ||
1047 | static struct dentry *try_to_ascend(struct dentry *old, unsigned seq) | ||
1048 | { | ||
1049 | struct dentry *new = old->d_parent; | ||
1050 | |||
1051 | rcu_read_lock(); | ||
1052 | spin_unlock(&old->d_lock); | ||
1053 | spin_lock(&new->d_lock); | ||
1054 | |||
1055 | /* | ||
1056 | * might go back up the wrong parent if we have had a rename | ||
1057 | * or deletion | ||
1058 | */ | ||
1059 | if (new != old->d_parent || | ||
1060 | (old->d_flags & DCACHE_DENTRY_KILLED) || | ||
1061 | need_seqretry(&rename_lock, seq)) { | ||
1062 | spin_unlock(&new->d_lock); | ||
1063 | new = NULL; | ||
1064 | } | ||
1065 | rcu_read_unlock(); | ||
1066 | return new; | ||
1067 | } | ||
1068 | |||
1069 | /** | 1041 | /** |
1070 | * enum d_walk_ret - action to talke during tree walk | 1042 | * enum d_walk_ret - action to talke during tree walk |
1071 | * @D_WALK_CONTINUE: contrinue walk | 1043 | * @D_WALK_CONTINUE: contrinue walk |
@@ -1154,9 +1126,24 @@ resume: | |||
1154 | */ | 1126 | */ |
1155 | if (this_parent != parent) { | 1127 | if (this_parent != parent) { |
1156 | struct dentry *child = this_parent; | 1128 | struct dentry *child = this_parent; |
1157 | this_parent = try_to_ascend(this_parent, seq); | 1129 | this_parent = child->d_parent; |
1158 | if (!this_parent) | 1130 | |
1131 | rcu_read_lock(); | ||
1132 | spin_unlock(&child->d_lock); | ||
1133 | spin_lock(&this_parent->d_lock); | ||
1134 | |||
1135 | /* | ||
1136 | * might go back up the wrong parent if we have had a rename | ||
1137 | * or deletion | ||
1138 | */ | ||
1139 | if (this_parent != child->d_parent || | ||
1140 | (child->d_flags & DCACHE_DENTRY_KILLED) || | ||
1141 | need_seqretry(&rename_lock, seq)) { | ||
1142 | spin_unlock(&this_parent->d_lock); | ||
1143 | rcu_read_unlock(); | ||
1159 | goto rename_retry; | 1144 | goto rename_retry; |
1145 | } | ||
1146 | rcu_read_unlock(); | ||
1160 | next = child->d_u.d_child.next; | 1147 | next = child->d_u.d_child.next; |
1161 | goto resume; | 1148 | goto resume; |
1162 | } | 1149 | } |