44#include "fscache.h"
55#include "../../dir.h"
66#include "config.h"
7+ #include "../../mem-pool.h"
78
89static volatile long initialized ;
910static DWORD dwTlsIndex ;
@@ -18,6 +19,7 @@ static CRITICAL_SECTION mutex;
1819struct fscache {
1920 volatile long enabled ;
2021 struct hashmap map ;
22+ struct mem_pool mem_pool ;
2123 unsigned int lstat_requests ;
2224 unsigned int opendir_requests ;
2325 unsigned int fscache_requests ;
@@ -122,11 +124,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
122124/*
123125 * Allocate an fsentry structure on the heap.
124126 */
125- static struct fsentry * fsentry_alloc (struct fsentry * list , const char * name ,
127+ static struct fsentry * fsentry_alloc (struct fscache * cache , struct fsentry * list , const char * name ,
126128 size_t len )
127129{
128130 /* overallocate fsentry and copy the name to the end */
129- struct fsentry * fse = xmalloc (sizeof (struct fsentry ) + len + 1 );
131+ struct fsentry * fse =
132+ mem_pool_alloc (& cache -> mem_pool , sizeof (* fse ) + len + 1 );
130133 /* init the rest of the structure */
131134 fsentry_init (fse , list , name , len );
132135 fse -> next = NULL ;
@@ -146,35 +149,29 @@ inline static void fsentry_addref(struct fsentry *fse)
146149}
147150
148151/*
149- * Release the reference to an fsentry, frees the memory if its the last ref .
152+ * Release the reference to an fsentry.
150153 */
151154static void fsentry_release (struct fsentry * fse )
152155{
153156 if (fse -> list )
154157 fse = fse -> list ;
155158
156- if (InterlockedDecrement (& (fse -> u .refcnt )))
157- return ;
158-
159- while (fse ) {
160- struct fsentry * next = fse -> next ;
161- free (fse );
162- fse = next ;
163- }
159+ InterlockedDecrement (& (fse -> u .refcnt ));
164160}
165161
166162/*
167163 * Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
168164 */
169- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
165+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
166+ struct fsentry * list ,
170167 const WIN32_FIND_DATAW * fdata )
171168{
172169 char buf [MAX_PATH * 3 ];
173170 int len ;
174171 struct fsentry * fse ;
175172 len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
176173
177- fse = fsentry_alloc (list , buf , len );
174+ fse = fsentry_alloc (cache , list , buf , len );
178175
179176 fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
180177 fse -> dirent .d_type = S_ISDIR (fse -> st_mode ) ? DT_DIR : DT_REG ;
@@ -192,7 +189,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
192189 * Dir should not contain trailing '/'. Use an empty string for the current
193190 * directory (not "."!).
194191 */
195- static struct fsentry * fsentry_create_list (const struct fsentry * dir ,
192+ static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
196193 int * dir_not_found )
197194{
198195 wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -231,14 +228,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
231228 }
232229
233230 /* allocate object to hold directory listing */
234- list = fsentry_alloc (NULL , dir -> dirent .d_name , dir -> len );
231+ list = fsentry_alloc (cache , NULL , dir -> dirent .d_name , dir -> len );
235232 list -> st_mode = S_IFDIR ;
236233 list -> dirent .d_type = DT_DIR ;
237234
238235 /* walk directory and build linked list of fsentry structures */
239236 phead = & list -> next ;
240237 do {
241- * phead = fseentry_create_entry (list , & fdata );
238+ * phead = fseentry_create_entry (cache , list , & fdata );
242239 phead = & (* phead )-> next ;
243240 } while (FindNextFileW (h , & fdata ));
244241
@@ -250,7 +247,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
250247 if (err == ERROR_NO_MORE_FILES )
251248 return list ;
252249
253- /* otherwise free the list and return error */
250+ /* otherwise release the list and return error */
254251 fsentry_release (list );
255252 errno = err_win_to_posix (err );
256253 return NULL ;
@@ -273,7 +270,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
273270 */
274271static void fscache_clear (struct fscache * cache )
275272{
276- hashmap_clear_and_free (& cache -> map , struct fsentry , ent );
273+ mem_pool_discard (& cache -> mem_pool , 0 );
274+ mem_pool_init (& cache -> mem_pool , 0 );
275+ hashmap_clear (& cache -> map );
277276 hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
278277 cache -> lstat_requests = cache -> opendir_requests = 0 ;
279278 cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -326,7 +325,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
326325 }
327326
328327 /* create the directory listing */
329- fse = fsentry_create_list (key -> list ? key -> list : key , & dir_not_found );
328+ fse = fsentry_create_list (cache , key -> list ? key -> list : key , & dir_not_found );
330329
331330 /* leave on error (errno set by fsentry_create_list) */
332331 if (!fse ) {
@@ -336,7 +335,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
336335 * empty, which for all practical matters is the same
337336 * thing as far as fscache is concerned).
338337 */
339- fse = fsentry_alloc (key -> list -> list ,
338+ fse = fsentry_alloc (cache , key -> list -> list ,
340339 key -> list -> dirent .d_name ,
341340 key -> list -> len );
342341 fse -> st_mode = 0 ;
@@ -415,6 +414,7 @@ int fscache_enable(size_t initial_size)
415414 * '4' was determined empirically by testing several repos
416415 */
417416 hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
417+ mem_pool_init (& cache -> mem_pool , 0 );
418418 if (!TlsSetValue (dwTlsIndex , cache ))
419419 BUG ("TlsSetValue error" );
420420 }
@@ -446,7 +446,8 @@ void fscache_disable(void)
446446 "total requests/misses %u/%u\n" ,
447447 cache -> lstat_requests , cache -> opendir_requests ,
448448 cache -> fscache_requests , cache -> fscache_misses );
449- fscache_clear (cache );
449+ mem_pool_discard (& cache -> mem_pool , 0 );
450+ hashmap_clear (& cache -> map );
450451 free (cache );
451452 }
452453
@@ -631,6 +632,8 @@ void fscache_merge(struct fscache *dest)
631632 while ((e = hashmap_iter_next (& iter )))
632633 hashmap_add (& dest -> map , e );
633634
635+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
636+
634637 dest -> lstat_requests += cache -> lstat_requests ;
635638 dest -> opendir_requests += cache -> opendir_requests ;
636639 dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments