Skip to content

Commit 867f72b

Browse files
torvaldsgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 443e061 commit 867f72b

File tree

1 file changed

+40
-35
lines changed

1 file changed

+40
-35
lines changed

symlinks.c

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ static struct cache_def {
3838
int flags;
3939
int track_flags;
4040
int prefix_len_stat_func;
41-
} cache;
41+
} default_cache;
4242

43-
static inline void reset_lstat_cache(void)
43+
static inline void reset_lstat_cache(struct cache_def *cache)
4444
{
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;
4848
/*
4949
* The track_flags and prefix_len_stat_func members is only
5050
* set by the safeguard rule inside lstat_cache()
@@ -70,34 +70,34 @@ static inline void reset_lstat_cache(void)
7070
* of the prefix, where the cache should use the stat() function
7171
* instead of the lstat() function to test each path component.
7272
*/
73-
static int lstat_cache(const char *name, int len,
73+
static int lstat_cache(struct cache_def *cache, const char *name, int len,
7474
int track_flags, int prefix_len_stat_func)
7575
{
7676
int match_len, last_slash, last_slash_dir, previous_slash;
7777
int match_flags, ret_flags, save_flags, max_len, ret;
7878
struct stat st;
7979

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) {
8282
/*
8383
* As a safeguard rule we clear the cache if the
8484
* values of track_flags and/or prefix_len_stat_func
8585
* does not match with the last supplied values.
8686
*/
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;
9090
match_len = last_slash = 0;
9191
} else {
9292
/*
9393
* Check to see if we have a match from the cache for
9494
* the 2 "excluding" path types.
9595
*/
9696
match_len = last_slash =
97-
longest_path_match(name, len, cache.path, cache.len,
97+
longest_path_match(name, len, cache->path, cache->len,
9898
&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)
101101
return match_flags;
102102
/*
103103
* If we now have match_len > 0, we would know that
@@ -121,18 +121,18 @@ static int lstat_cache(const char *name, int len,
121121
max_len = len < PATH_MAX ? len : PATH_MAX;
122122
while (match_len < max_len) {
123123
do {
124-
cache.path[match_len] = name[match_len];
124+
cache->path[match_len] = name[match_len];
125125
match_len++;
126126
} while (match_len < max_len && name[match_len] != '/');
127127
if (match_len >= max_len && !(track_flags & FL_FULLPATH))
128128
break;
129129
last_slash = match_len;
130-
cache.path[last_slash] = '\0';
130+
cache->path[last_slash] = '\0';
131131

132132
if (last_slash <= prefix_len_stat_func)
133-
ret = stat(cache.path, &st);
133+
ret = stat(cache->path, &st);
134134
else
135-
ret = lstat(cache.path, &st);
135+
ret = lstat(cache->path, &st);
136136

137137
if (ret) {
138138
ret_flags = FL_LSTATERR;
@@ -156,9 +156,9 @@ static int lstat_cache(const char *name, int len,
156156
*/
157157
save_flags = ret_flags & track_flags & (FL_NOENT|FL_SYMLINK);
158158
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;
162162
} else if ((track_flags & FL_DIR) &&
163163
last_slash_dir > 0 && last_slash_dir <= PATH_MAX) {
164164
/*
@@ -172,11 +172,11 @@ static int lstat_cache(const char *name, int len,
172172
* can still cache the path components before the last
173173
* one (the found symlink or non-existing component).
174174
*/
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;
178178
} else {
179-
reset_lstat_cache();
179+
reset_lstat_cache(cache);
180180
}
181181
return ret_flags;
182182
}
@@ -188,16 +188,17 @@ static int lstat_cache(const char *name, int len,
188188
void invalidate_lstat_cache(const char *name, int len)
189189
{
190190
int match_len, previous_slash;
191+
struct cache_def *cache = &default_cache; /* FIXME */
191192

192-
match_len = longest_path_match(name, len, cache.path, cache.len,
193+
match_len = longest_path_match(name, len, cache->path, cache->len,
193194
&previous_slash);
194195
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;
199200
} else {
200-
reset_lstat_cache();
201+
reset_lstat_cache(cache);
201202
}
202203
}
203204
}
@@ -207,7 +208,8 @@ void invalidate_lstat_cache(const char *name, int len)
207208
*/
208209
void clear_lstat_cache(void)
209210
{
210-
reset_lstat_cache();
211+
struct cache_def *cache = &default_cache; /* FIXME */
212+
reset_lstat_cache(cache);
211213
}
212214

213215
#define USE_ONLY_LSTAT 0
@@ -217,7 +219,8 @@ void clear_lstat_cache(void)
217219
*/
218220
int has_symlink_leading_path(const char *name, int len)
219221
{
220-
return lstat_cache(name, len,
222+
struct cache_def *cache = &default_cache; /* FIXME */
223+
return lstat_cache(cache, name, len,
221224
FL_SYMLINK|FL_DIR, USE_ONLY_LSTAT) &
222225
FL_SYMLINK;
223226
}
@@ -228,7 +231,8 @@ int has_symlink_leading_path(const char *name, int len)
228231
*/
229232
int has_symlink_or_noent_leading_path(const char *name, int len)
230233
{
231-
return lstat_cache(name, len,
234+
struct cache_def *cache = &default_cache; /* FIXME */
235+
return lstat_cache(cache, name, len,
232236
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT) &
233237
(FL_SYMLINK|FL_NOENT);
234238
}
@@ -242,7 +246,8 @@ int has_symlink_or_noent_leading_path(const char *name, int len)
242246
*/
243247
int has_dirs_only_path(const char *name, int len, int prefix_len)
244248
{
245-
return lstat_cache(name, len,
249+
struct cache_def *cache = &default_cache; /* FIXME */
250+
return lstat_cache(cache, name, len,
246251
FL_DIR|FL_FULLPATH, prefix_len) &
247252
FL_DIR;
248253
}

0 commit comments

Comments
 (0)