@@ -12,23 +12,30 @@ static struct cache_def {
1212 * Returns the length (on a path component basis) of the longest
1313 * common prefix match of 'name' and the cached path string.
1414 */
15- static inline int longest_match_lstat_cache (int len , const char * name )
15+ static inline int longest_match_lstat_cache (int len , const char * name ,
16+ int * previous_slash )
1617{
17- int max_len , match_len = 0 , i = 0 ;
18+ int max_len , match_len = 0 , match_len_prev = 0 , i = 0 ;
1819
1920 max_len = len < cache .len ? len : cache .len ;
2021 while (i < max_len && name [i ] == cache .path [i ]) {
21- if (name [i ] == '/' )
22+ if (name [i ] == '/' ) {
23+ match_len_prev = match_len ;
2224 match_len = i ;
25+ }
2326 i ++ ;
2427 }
2528 /* Is the cached path string a substring of 'name'? */
26- if (i == cache .len && cache .len < len && name [cache .len ] == '/' )
29+ if (i == cache .len && cache .len < len && name [cache .len ] == '/' ) {
30+ match_len_prev = match_len ;
2731 match_len = cache .len ;
2832 /* Is 'name' a substring of the cached path string? */
29- else if ((i == len && len < cache .len && cache .path [len ] == '/' ) ||
30- (i == len && len == cache .len ))
33+ } else if ((i == len && len < cache .len && cache .path [len ] == '/' ) ||
34+ (i == len && len == cache .len )) {
35+ match_len_prev = match_len ;
3136 match_len = len ;
37+ }
38+ * previous_slash = match_len_prev ;
3239 return match_len ;
3340}
3441
@@ -63,7 +70,7 @@ static inline void reset_lstat_cache(int track_flags, int prefix_len_stat_func)
6370static int lstat_cache (int len , const char * name ,
6471 int track_flags , int prefix_len_stat_func )
6572{
66- int match_len , last_slash , last_slash_dir ;
73+ int match_len , last_slash , last_slash_dir , previous_slash ;
6774 int match_flags , ret_flags , save_flags , max_len , ret ;
6875 struct stat st ;
6976
@@ -81,7 +88,8 @@ static int lstat_cache(int len, const char *name,
8188 * Check to see if we have a match from the cache for
8289 * the 2 "excluding" path types.
8390 */
84- match_len = last_slash = longest_match_lstat_cache (len , name );
91+ match_len = last_slash =
92+ longest_match_lstat_cache (len , name , & previous_slash );
8593 match_flags = cache .flags & track_flags & (FL_NOENT |FL_SYMLINK );
8694 if (match_flags && match_len == cache .len )
8795 return match_flags ;
@@ -167,6 +175,26 @@ static int lstat_cache(int len, const char *name,
167175 return ret_flags ;
168176}
169177
178+ /*
179+ * Invalidate the given 'name' from the cache, if 'name' matches
180+ * completely with the cache.
181+ */
182+ void invalidate_lstat_cache (int len , const char * name )
183+ {
184+ int match_len , previous_slash ;
185+
186+ match_len = longest_match_lstat_cache (len , name , & previous_slash );
187+ if (len == match_len ) {
188+ if ((cache .track_flags & FL_DIR ) && previous_slash > 0 ) {
189+ cache .path [previous_slash ] = '\0' ;
190+ cache .len = previous_slash ;
191+ cache .flags = FL_DIR ;
192+ } else
193+ reset_lstat_cache (cache .track_flags ,
194+ cache .prefix_len_stat_func );
195+ }
196+ }
197+
170198#define USE_ONLY_LSTAT 0
171199
172200/*
0 commit comments