@matheusbsbs / matheus-bagliano / commits / 867f72bf43
Fork 0

Prepare symlink caching for thread-safety

This doesn't actually change the external interfaces, so they are still thread-unsafe, but it makes the code internally pass a pointer to a local 'struct cache_def' around, so that the core code can be made thread-safe. The threaded index preloading will want to verify that the paths leading up to a pathname are all real directories. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Linus Torvalds committed Jul 9, 2009 at 13:23 UTC 867f72bf434a05b9eadf851a81564be5173fbba5
1 file changed +40 -35
symlinks.c
+40 -35
@@ -38,13 +38,13 @@ static struct cache_def {
38 int flags;
39 int track_flags;
40 int prefix_len_stat_func;
41 -} cache;
41 +} default_cache;
42
43 -static inline void reset_lstat_cache(void)
43 +static inline void reset_lstat_cache(struct cache_def *cache)
44 {
45 - cache.path[0] = '\0';
46 - cache.len = 0;
47 - cache.flags = 0;
45 + cache->path[0] = '\0';
46 + cache->len = 0;
47 + cache->flags = 0;
48 /*
49 * The track_flags and prefix_len_stat_func members is only
50 * set by the safeguard rule inside lstat_cache()
@@ -70,23 +70,23 @@ static inline void reset_lstat_cache(void)
70 * of the prefix, where the cache should use the stat() function
71 * instead of the lstat() function to test each path component.
72 */
73 -static int lstat_cache(const char *name, int len,
73 +static int lstat_cache(struct cache_def *cache, const char *name, int len,
74 int track_flags, int prefix_len_stat_func)
75 {
76 int match_len, last_slash, last_slash_dir, previous_slash;
77 int match_flags, ret_flags, save_flags, max_len, ret;
78 struct stat st;
79
80 - if (cache.track_flags != track_flags ||
81 - cache.prefix_len_stat_func != prefix_len_stat_func) {
80 + if (cache->track_flags != track_flags ||
81 + cache->prefix_len_stat_func != prefix_len_stat_func) {
82 /*
83 * As a safeguard rule we clear the cache if the
84 * values of track_flags and/or prefix_len_stat_func
85 * does not match with the last supplied values.
86 */
87 - reset_lstat_cache();
88 - cache.track_flags = track_flags;
89 - cache.prefix_len_stat_func = prefix_len_stat_func;
87 + reset_lstat_cache(cache);
88 + cache->track_flags = track_flags;
89 + cache->prefix_len_stat_func = prefix_len_stat_func;
90 match_len = last_slash = 0;
91 } else {
92 /*
@@ -94,10 +94,10 @@ static int lstat_cache(const char *name, int len,
94 * the 2 "excluding" path types.
95 */
96 match_len = last_slash =
97 - longest_path_match(name, len, cache.path, cache.len,
97 + longest_path_match(name, len, cache->path, cache->len,
98 &previous_slash);
99 - match_flags = cache.flags & track_flags & (FL_NOENT|FL_SYMLINK);
100 - if (match_flags && match_len == cache.len)
99 + match_flags = cache->flags & track_flags & (FL_NOENT|FL_SYMLINK);
100 + if (match_flags && match_len == cache->len)
101 return match_flags;
102 /*
103 * If we now have match_len > 0, we would know that
@@ -121,18 +121,18 @@ static int lstat_cache(const char *name, int len,
121 max_len = len < PATH_MAX ? len : PATH_MAX;
122 while (match_len < max_len) {
123 do {
124 - cache.path[match_len] = name[match_len];
124 + cache->path[match_len] = name[match_len];
125 match_len++;
126 } while (match_len < max_len && name[match_len] != '/');
127 if (match_len >= max_len && !(track_flags & FL_FULLPATH))
128 break;
129 last_slash = match_len;
130 - cache.path[last_slash] = '\0';
130 + cache->path[last_slash] = '\0';
131
132 if (last_slash <= prefix_len_stat_func)
133 - ret = stat(cache.path, &st);
133 + ret = stat(cache->path, &st);
134 else
135 - ret = lstat(cache.path, &st);
135 + ret = lstat(cache->path, &st);
136
137 if (ret) {
138 ret_flags = FL_LSTATERR;
@@ -156,9 +156,9 @@ static int lstat_cache(const char *name, int len,
156 */
157 save_flags = ret_flags & track_flags & (FL_NOENT|FL_SYMLINK);
158 if (save_flags && last_slash > 0 && last_slash <= PATH_MAX) {
159 - cache.path[last_slash] = '\0';
160 - cache.len = last_slash;
161 - cache.flags = save_flags;
159 + cache->path[last_slash] = '\0';
160 + cache->len = last_slash;
161 + cache->flags = save_flags;
162 } else if ((track_flags & FL_DIR) &&
163 last_slash_dir > 0 && last_slash_dir <= PATH_MAX) {
164 /*
@@ -172,11 +172,11 @@ static int lstat_cache(const char *name, int len,
172 * can still cache the path components before the last
173 * one (the found symlink or non-existing component).
174 */
175 - cache.path[last_slash_dir] = '\0';
176 - cache.len = last_slash_dir;
177 - cache.flags = FL_DIR;
175 + cache->path[last_slash_dir] = '\0';
176 + cache->len = last_slash_dir;
177 + cache->flags = FL_DIR;
178 } else {
179 - reset_lstat_cache();
179 + reset_lstat_cache(cache);
180 }
181 return ret_flags;
182 }
@@ -188,16 +188,17 @@ static int lstat_cache(const char *name, int len,
188 void invalidate_lstat_cache(const char *name, int len)
189 {
190 int match_len, previous_slash;
191 + struct cache_def *cache = &default_cache; /* FIXME */
192
192 - match_len = longest_path_match(name, len, cache.path, cache.len,
193 + match_len = longest_path_match(name, len, cache->path, cache->len,
194 &previous_slash);
195 if (len == match_len) {
195 - if ((cache.track_flags & FL_DIR) && previous_slash > 0) {
196 - cache.path[previous_slash] = '\0';
197 - cache.len = previous_slash;
198 - cache.flags = FL_DIR;
196 + if ((cache->track_flags & FL_DIR) && previous_slash > 0) {
197 + cache->path[previous_slash] = '\0';
198 + cache->len = previous_slash;
199 + cache->flags = FL_DIR;
200 } else {
200 - reset_lstat_cache();
201 + reset_lstat_cache(cache);
202 }
203 }
204 }
@@ -207,7 +208,8 @@ void invalidate_lstat_cache(const char *name, int len)
208 */
209 void clear_lstat_cache(void)
210 {
210 - reset_lstat_cache();
211 + struct cache_def *cache = &default_cache; /* FIXME */
212 + reset_lstat_cache(cache);
213 }
214
215 #define USE_ONLY_LSTAT 0
@@ -217,7 +219,8 @@ void clear_lstat_cache(void)
219 */
220 int has_symlink_leading_path(const char *name, int len)
221 {
220 - return lstat_cache(name, len,
222 + struct cache_def *cache = &default_cache; /* FIXME */
223 + return lstat_cache(cache, name, len,
224 FL_SYMLINK|FL_DIR, USE_ONLY_LSTAT) &
225 FL_SYMLINK;
226 }
@@ -228,7 +231,8 @@ int has_symlink_leading_path(const char *name, int len)
231 */
232 int has_symlink_or_noent_leading_path(const char *name, int len)
233 {
231 - return lstat_cache(name, len,
234 + struct cache_def *cache = &default_cache; /* FIXME */
235 + return lstat_cache(cache, name, len,
236 FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT) &
237 (FL_SYMLINK|FL_NOENT);
238 }
@@ -242,7 +246,8 @@ int has_symlink_or_noent_leading_path(const char *name, int len)
246 */
247 int has_dirs_only_path(const char *name, int len, int prefix_len)
248 {
245 - return lstat_cache(name, len,
249 + struct cache_def *cache = &default_cache; /* FIXME */
250 + return lstat_cache(cache, name, len,
251 FL_DIR|FL_FULLPATH, prefix_len) &
252 FL_DIR;
253 }