Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fscache: add not-found directory cache to fscache #994

Merged
merged 2 commits into from
Jan 25, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions compat/win32/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ static int initialized;
static volatile long enabled;
static struct hashmap map;
static CRITICAL_SECTION mutex;
static struct trace_key trace_fscache = TRACE_KEY_INIT(FSCACHE);

/*
* An entry in the file system cache. Used for both entire directory listings
Expand Down Expand Up @@ -163,7 +164,8 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
* Dir should not contain trailing '/'. Use an empty string for the current
* directory (not "."!).
*/
static struct fsentry *fsentry_create_list(const struct fsentry *dir)
static struct fsentry *fsentry_create_list(const struct fsentry *dir,
int *dir_not_found)
{
wchar_t pattern[MAX_LONG_PATH + 2]; /* + 2 for "\*" */
WIN32_FIND_DATAW fdata;
Expand All @@ -172,6 +174,8 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir)
struct fsentry *list, **phead;
DWORD err;

*dir_not_found = 0;

/* convert name to UTF-16 and check length */
if ((wlen = xutftowcs_path_ex(pattern, dir->name, MAX_LONG_PATH,
dir->len, MAX_PATH - 2, core_long_paths)) < 0)
Expand All @@ -190,12 +194,16 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir)
h = FindFirstFileW(pattern, &fdata);
if (h == INVALID_HANDLE_VALUE) {
err = GetLastError();
*dir_not_found = 1; /* or empty directory */
errno = (err == ERROR_DIRECTORY) ? ENOTDIR : err_win_to_posix(err);
trace_printf_key(&trace_fscache, "fscache: error(%d) '%.*s'\n",
errno, dir->len, dir->name);
return NULL;
}

/* allocate object to hold directory listing */
list = fsentry_alloc(NULL, dir->name, dir->len);
list->st_mode = S_IFDIR;

/* walk directory and build linked list of fsentry structures */
phead = &list->next;
Expand Down Expand Up @@ -296,12 +304,16 @@ static struct fsentry *fscache_get_wait(struct fsentry *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) {
fsentry_addref(fse);
if (fse->st_mode)
fsentry_addref(fse);
else
fse = NULL; /* non-existing directory */
LeaveCriticalSection(&mutex);
return fse;
}
Expand All @@ -310,7 +322,10 @@ static struct fsentry *fscache_get(struct fsentry *key)
fse = fscache_get_wait(key->list);
if (fse) {
LeaveCriticalSection(&mutex);
/* dir entry without file entry -> file doesn't exist */
/*
* dir entry without file entry, or dir does not
* exist -> file doesn't exist
*/
errno = ENOENT;
return NULL;
}
Expand All @@ -324,7 +339,7 @@ static struct fsentry *fscache_get(struct fsentry *key)

/* create the directory listing (outside mutex!) */
LeaveCriticalSection(&mutex);
fse = fsentry_create_list(future);
fse = fsentry_create_list(future, &dir_not_found);
EnterCriticalSection(&mutex);

/* remove future entry and signal waiting threads */
Expand All @@ -338,6 +353,17 @@ static struct fsentry *fscache_get(struct fsentry *key)

/* 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;
}
Expand All @@ -349,6 +375,9 @@ static struct fsentry *fscache_get(struct fsentry *key)
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);
Expand Down Expand Up @@ -392,6 +421,7 @@ int fscache_enable(int enable)
fscache_clear();
LeaveCriticalSection(&mutex);
}
trace_printf_key(&trace_fscache, "fscache: enable(%d)\n", enable);
return result;
}

Expand Down