Commit c826cb7dfce80512c26c984350077a25046bd215

Authored by Linus Torvalds
1 parent 76ca078328

dcache.c: create helper function for duplicated functionality

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>

Showing 1 changed file with 37 additions and 51 deletions Side-by-side Diff

... ... @@ -1012,6 +1012,34 @@
1012 1012 }
1013 1013  
1014 1014 /*
  1015 + * This tries to ascend one level of parenthood, but
  1016 + * we can race with renaming, so we need to re-check
  1017 + * the parenthood after dropping the lock and check
  1018 + * that the sequence number still matches.
  1019 + */
  1020 +static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq)
  1021 +{
  1022 + struct dentry *new = old->d_parent;
  1023 +
  1024 + rcu_read_lock();
  1025 + spin_unlock(&old->d_lock);
  1026 + spin_lock(&new->d_lock);
  1027 +
  1028 + /*
  1029 + * might go back up the wrong parent if we have had a rename
  1030 + * or deletion
  1031 + */
  1032 + if (new != old->d_parent ||
  1033 + (!locked && read_seqretry(&rename_lock, seq))) {
  1034 + spin_unlock(&new->d_lock);
  1035 + new = NULL;
  1036 + }
  1037 + rcu_read_unlock();
  1038 + return new;
  1039 +}
  1040 +
  1041 +
  1042 +/*
1015 1043 * Search for at least 1 mount point in the dentry's subdirs.
1016 1044 * We descend to the next level whenever the d_subdirs
1017 1045 * list is non-empty and continue searching.
1018 1046  
... ... @@ -1066,24 +1094,10 @@
1066 1094 * All done at this level ... ascend and resume the search.
1067 1095 */
1068 1096 if (this_parent != parent) {
1069   - struct dentry *tmp;
1070   - struct dentry *child;
1071   -
1072   - tmp = this_parent->d_parent;
1073   - rcu_read_lock();
1074   - spin_unlock(&this_parent->d_lock);
1075   - child = this_parent;
1076   - this_parent = tmp;
1077   - spin_lock(&this_parent->d_lock);
1078   - /* might go back up the wrong parent if we have had a rename
1079   - * or deletion */
1080   - if (this_parent != child->d_parent ||
1081   - (!locked && read_seqretry(&rename_lock, seq))) {
1082   - spin_unlock(&this_parent->d_lock);
1083   - rcu_read_unlock();
  1097 + struct dentry *child = this_parent;
  1098 + this_parent = try_to_ascend(this_parent, locked, seq);
  1099 + if (!this_parent)
1084 1100 goto rename_retry;
1085   - }
1086   - rcu_read_unlock();
1087 1101 next = child->d_u.d_child.next;
1088 1102 goto resume;
1089 1103 }
1090 1104  
... ... @@ -1181,24 +1195,10 @@
1181 1195 * All done at this level ... ascend and resume the search.
1182 1196 */
1183 1197 if (this_parent != parent) {
1184   - struct dentry *tmp;
1185   - struct dentry *child;
1186   -
1187   - tmp = this_parent->d_parent;
1188   - rcu_read_lock();
1189   - spin_unlock(&this_parent->d_lock);
1190   - child = this_parent;
1191   - this_parent = tmp;
1192   - spin_lock(&this_parent->d_lock);
1193   - /* might go back up the wrong parent if we have had a rename
1194   - * or deletion */
1195   - if (this_parent != child->d_parent ||
1196   - (!locked && read_seqretry(&rename_lock, seq))) {
1197   - spin_unlock(&this_parent->d_lock);
1198   - rcu_read_unlock();
  1198 + struct dentry *child = this_parent;
  1199 + this_parent = try_to_ascend(this_parent, locked, seq);
  1200 + if (!this_parent)
1199 1201 goto rename_retry;
1200   - }
1201   - rcu_read_unlock();
1202 1202 next = child->d_u.d_child.next;
1203 1203 goto resume;
1204 1204 }
1205 1205  
1206 1206  
... ... @@ -2942,28 +2942,14 @@
2942 2942 spin_unlock(&dentry->d_lock);
2943 2943 }
2944 2944 if (this_parent != root) {
2945   - struct dentry *tmp;
2946   - struct dentry *child;
2947   -
2948   - tmp = this_parent->d_parent;
  2945 + struct dentry *child = this_parent;
2949 2946 if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
2950 2947 this_parent->d_flags |= DCACHE_GENOCIDE;
2951 2948 this_parent->d_count--;
2952 2949 }
2953   - rcu_read_lock();
2954   - spin_unlock(&this_parent->d_lock);
2955   - child = this_parent;
2956   - this_parent = tmp;
2957   - spin_lock(&this_parent->d_lock);
2958   - /* might go back up the wrong parent if we have had a rename
2959   - * or deletion */
2960   - if (this_parent != child->d_parent ||
2961   - (!locked && read_seqretry(&rename_lock, seq))) {
2962   - spin_unlock(&this_parent->d_lock);
2963   - rcu_read_unlock();
  2950 + this_parent = try_to_ascend(this_parent, locked, seq);
  2951 + if (!this_parent)
2964 2952 goto rename_retry;
2965   - }
2966   - rcu_read_unlock();
2967 2953 next = child->d_u.d_child.next;
2968 2954 goto resume;
2969 2955 }