/* * Looks up or creates a cache entry for the specified key. */ static struct fsentry *fscache_get(struct fsentry *key) { struct fsentry *fse, *future, *waiter; int dir_not_found; EnterCriticalSection(&mutex); /* check if entry is in cache */ fse = fscache_get_wait(key); if (fse) { if (fse->st_mode) fsentry_addref(fse); else fse = NULL; /* non-existing directory */ LeaveCriticalSection(&mutex); return fse; } /* if looking for a file, check if directory listing is in cache */ if (!fse && key->list) { fse = fscache_get_wait(key->list); if (fse) { LeaveCriticalSection(&mutex); /* * dir entry without file entry, or dir does not * exist -> file doesn't exist */ errno = ENOENT; return NULL; } } /* add future entry to indicate that we're loading it */ future = key->list ? key->list : key; future->next = NULL; future->refcnt = 0; hashmap_add(&map, future); /* create the directory listing (outside mutex!) */ LeaveCriticalSection(&mutex); fse = fsentry_create_list(future, &dir_not_found); EnterCriticalSection(&mutex); /* remove future entry and signal waiting threads */ hashmap_remove(&map, future, NULL); waiter = future->next; while (waiter) { HANDLE h = waiter->hwait; waiter = waiter->next; SetEvent(h); } /* leave on error (errno set by fsentry_create_list) */ if (!fse) { if (dir_not_found && key->list) { /* * Record that the directory does not exist (or is * empty, which for all practical matters is the same * thing as far as fscache is concerned). */ fse = fsentry_alloc(key->list->list, key->list->name, key->list->len); fse->st_mode = 0; hashmap_add(&map, fse); } LeaveCriticalSection(&mutex); return NULL; } /* add directory listing to the cache */ fscache_add(fse); /* lookup file entry if requested (fse already points to directory) */ if (key->list) fse = hashmap_get(&map, key, NULL); if (fse && !fse->st_mode) fse = NULL; /* non-existing directory */ /* return entry or ENOENT */ if (fse) fsentry_addref(fse); else errno = ENOENT; LeaveCriticalSection(&mutex); return fse; }
/* * Looks up or creates a cache entry for the specified key. */ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key) { struct fsentry *fse; int dir_not_found; cache->fscache_requests++; /* check if entry is in cache */ fse = hashmap_get(&cache->map, key, NULL); if (fse) { if (fse->st_mode) fsentry_addref(fse); else fse = NULL; /* non-existing directory */ return fse; } /* if looking for a file, check if directory listing is in cache */ if (!fse && key->list) { fse = hashmap_get(&cache->map, key->list, NULL); if (fse) { /* * dir entry without file entry, or dir does not * exist -> file doesn't exist */ errno = ENOENT; return NULL; } } /* create the directory listing */ fse = fsentry_create_list(cache, key->list ? key->list : key, &dir_not_found); /* leave on error (errno set by fsentry_create_list) */ if (!fse) { if (dir_not_found && key->list) { /* * Record that the directory does not exist (or is * empty, which for all practical matters is the same * thing as far as fscache is concerned). */ fse = fsentry_alloc(cache, key->list->list, key->list->name, key->list->len); fse->st_mode = 0; hashmap_add(&cache->map, fse); } return NULL; } /* add directory listing to the cache */ cache->fscache_misses++; fscache_add(cache, fse); /* lookup file entry if requested (fse already points to directory) */ if (key->list) fse = hashmap_get(&cache->map, key, NULL); if (fse && !fse->st_mode) fse = NULL; /* non-existing directory */ /* return entry or ENOENT */ if (fse) fsentry_addref(fse); else errno = ENOENT; return fse; }
/* * Looks up or creates a cache entry for the specified key. */ static struct fsentry *fscache_get(struct fsentry *key) { struct fsentry *fse, *future, *waiter; EnterCriticalSection(&mutex); /* check if entry is in cache */ fse = fscache_get_wait(key); if (fse) { fsentry_addref(fse); LeaveCriticalSection(&mutex); return fse; } /* if looking for a file, check if directory listing is in cache */ if (!fse && key->list) { fse = fscache_get_wait(key->list); if (fse) { LeaveCriticalSection(&mutex); /* dir entry without file entry -> file doesn't exist */ errno = ENOENT; return NULL; } } /* add future entry to indicate that we're loading it */ future = key->list ? key->list : key; future->next = NULL; future->refcnt = 0; hashmap_add(&map, future); /* create the directory listing (outside mutex!) */ LeaveCriticalSection(&mutex); fse = fsentry_create_list(future); EnterCriticalSection(&mutex); /* remove future entry and signal waiting threads */ hashmap_remove(&map, future, NULL); waiter = future->next; while (waiter) { HANDLE h = waiter->hwait; waiter = waiter->next; SetEvent(h); } /* leave on error (errno set by fsentry_create_list) */ if (!fse) { LeaveCriticalSection(&mutex); return NULL; } /* add directory listing to the cache */ fscache_add(fse); /* lookup file entry if requested (fse already points to directory) */ if (key->list) fse = hashmap_get(&map, key, NULL); /* return entry or ENOENT */ if (fse) fsentry_addref(fse); else errno = ENOENT; LeaveCriticalSection(&mutex); return fse; }