aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c86
1 files changed, 21 insertions, 65 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 0a38ef8d7f00..6055d61811d3 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -88,35 +88,6 @@ EXPORT_SYMBOL(rename_lock);
88 88
89static struct kmem_cache *dentry_cache __read_mostly; 89static struct kmem_cache *dentry_cache __read_mostly;
90 90
91/**
92 * read_seqbegin_or_lock - begin a sequence number check or locking block
93 * @lock: sequence lock
94 * @seq : sequence number to be checked
95 *
96 * First try it once optimistically without taking the lock. If that fails,
97 * take the lock. The sequence number is also used as a marker for deciding
98 * whether to be a reader (even) or writer (odd).
99 * N.B. seq must be initialized to an even number to begin with.
100 */
101static inline void read_seqbegin_or_lock(seqlock_t *lock, int *seq)
102{
103 if (!(*seq & 1)) /* Even */
104 *seq = read_seqbegin(lock);
105 else /* Odd */
106 read_seqlock_excl(lock);
107}
108
109static inline int need_seqretry(seqlock_t *lock, int seq)
110{
111 return !(seq & 1) && read_seqretry(lock, seq);
112}
113
114static inline void done_seqretry(seqlock_t *lock, int seq)
115{
116 if (seq & 1)
117 read_sequnlock_excl(lock);
118}
119
120/* 91/*
121 * This is the single most critical data structure when it comes 92 * This is the single most critical data structure when it comes
122 * to the dcache: the hashtable for lookups. Somebody should try 93 * to the dcache: the hashtable for lookups. Somebody should try
@@ -125,8 +96,6 @@ static inline void done_seqretry(seqlock_t *lock, int seq)
125 * This hash-function tries to avoid losing too many bits of hash 96 * This hash-function tries to avoid losing too many bits of hash
126 * information, yet avoid using a prime hash-size or similar. 97 * information, yet avoid using a prime hash-size or similar.
127 */ 98 */
128#define D_HASHBITS d_hash_shift
129#define D_HASHMASK d_hash_mask
130 99
131static unsigned int d_hash_mask __read_mostly; 100static unsigned int d_hash_mask __read_mostly;
132static unsigned int d_hash_shift __read_mostly; 101static unsigned int d_hash_shift __read_mostly;
@@ -137,8 +106,8 @@ static inline struct hlist_bl_head *d_hash(const struct dentry *parent,
137 unsigned int hash) 106 unsigned int hash)
138{ 107{
139 hash += (unsigned long) parent / L1_CACHE_BYTES; 108 hash += (unsigned long) parent / L1_CACHE_BYTES;
140 hash = hash + (hash >> D_HASHBITS); 109 hash = hash + (hash >> d_hash_shift);
141 return dentry_hashtable + (hash & D_HASHMASK); 110 return dentry_hashtable + (hash & d_hash_mask);
142} 111}
143 112
144/* Statistics gathering. */ 113/* Statistics gathering. */
@@ -223,7 +192,7 @@ static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char
223 if (!tcount) 192 if (!tcount)
224 return 0; 193 return 0;
225 } 194 }
226 mask = ~(~0ul << tcount*8); 195 mask = bytemask_from_count(tcount);
227 return unlikely(!!((a ^ b) & mask)); 196 return unlikely(!!((a ^ b) & mask));
228} 197}
229 198
@@ -469,7 +438,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
469{ 438{
470 list_del(&dentry->d_u.d_child); 439 list_del(&dentry->d_u.d_child);
471 /* 440 /*
472 * Inform try_to_ascend() that we are no longer attached to the 441 * Inform d_walk() that we are no longer attached to the
473 * dentry tree 442 * dentry tree
474 */ 443 */
475 dentry->d_flags |= DCACHE_DENTRY_KILLED; 444 dentry->d_flags |= DCACHE_DENTRY_KILLED;
@@ -1069,34 +1038,6 @@ void shrink_dcache_sb(struct super_block *sb)
1069} 1038}
1070EXPORT_SYMBOL(shrink_dcache_sb); 1039EXPORT_SYMBOL(shrink_dcache_sb);
1071 1040
1072/*
1073 * This tries to ascend one level of parenthood, but
1074 * we can race with renaming, so we need to re-check
1075 * the parenthood after dropping the lock and check
1076 * that the sequence number still matches.
1077 */
1078static struct dentry *try_to_ascend(struct dentry *old, unsigned seq)
1079{
1080 struct dentry *new = old->d_parent;
1081
1082 rcu_read_lock();
1083 spin_unlock(&old->d_lock);
1084 spin_lock(&new->d_lock);
1085
1086 /*
1087 * might go back up the wrong parent if we have had a rename
1088 * or deletion
1089 */
1090 if (new != old->d_parent ||
1091 (old->d_flags & DCACHE_DENTRY_KILLED) ||
1092 need_seqretry(&rename_lock, seq)) {
1093 spin_unlock(&new->d_lock);
1094 new = NULL;
1095 }
1096 rcu_read_unlock();
1097 return new;
1098}
1099
1100/** 1041/**
1101 * enum d_walk_ret - action to talke during tree walk 1042 * enum d_walk_ret - action to talke during tree walk
1102 * @D_WALK_CONTINUE: contrinue walk 1043 * @D_WALK_CONTINUE: contrinue walk
@@ -1185,9 +1126,24 @@ resume:
1185 */ 1126 */
1186 if (this_parent != parent) { 1127 if (this_parent != parent) {
1187 struct dentry *child = this_parent; 1128 struct dentry *child = this_parent;
1188 this_parent = try_to_ascend(this_parent, seq); 1129 this_parent = child->d_parent;
1189 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();
1190 goto rename_retry; 1144 goto rename_retry;
1145 }
1146 rcu_read_unlock();
1191 next = child->d_u.d_child.next; 1147 next = child->d_u.d_child.next;
1192 goto resume; 1148 goto resume;
1193 } 1149 }