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
}