fscache: implement an FSCache-aware is_mount_point()

When FSCache is active, we can cache the reparse tag and use it directly
to determine whether a path refers to an NTFS junction, without any
additional, costly I/O.

Note: this change only makes a difference with the next commit, which
will make use of the FSCache in `git clean` (contingent on
`core.fscache` set, of course).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2018-12-11 12:17:49 +01:00
Родитель ae6718cbf9
Коммит d992ff7c2a
4 изменённых файлов: 40 добавлений и 1 удалений

Просмотреть файл

@ -2709,6 +2709,8 @@ pid_t waitpid(pid_t pid, int *status, int options)
return -1;
}
int (*win32_is_mount_point)(struct strbuf *path) = mingw_is_mount_point;
int mingw_is_mount_point(struct strbuf *path)
{
WIN32_FIND_DATAW findbuf = { 0 };

Просмотреть файл

@ -471,7 +471,8 @@ static inline void convert_slashes(char *path)
}
struct strbuf;
int mingw_is_mount_point(struct strbuf *path);
#define is_mount_point mingw_is_mount_point
extern int (*win32_is_mount_point)(struct strbuf *path);
#define is_mount_point win32_is_mount_point
#define CAN_UNLINK_MOUNT_POINTS 1
#define PATH_SEP ';'
char *mingw_query_user_email(void);

Просмотреть файл

@ -467,6 +467,7 @@ int fscache_enable(size_t initial_size)
/* redirect opendir and lstat to the fscache implementations */
opendir = fscache_opendir;
lstat = fscache_lstat;
win32_is_mount_point = fscache_is_mount_point;
}
initialized++;
LeaveCriticalSection(&fscache_cs);
@ -527,6 +528,7 @@ void fscache_disable(void)
/* reset opendir and lstat to the original implementations */
opendir = dirent_opendir;
lstat = mingw_lstat;
win32_is_mount_point = mingw_is_mount_point;
}
LeaveCriticalSection(&fscache_cs);
@ -597,6 +599,39 @@ int fscache_lstat(const char *filename, struct stat *st)
return 0;
}
/*
* is_mount_point() replacement, uses cache if enabled, otherwise falls
* back to mingw_is_mount_point().
*/
int fscache_is_mount_point(struct strbuf *path)
{
int dirlen, base, len;
struct heap_fsentry key[2];
struct fsentry *fse;
struct fscache *cache = fscache_getcache();
if (!cache || !do_fscache_enabled(cache, path->buf))
return mingw_is_mount_point(path);
cache->lstat_requests++;
/* split path into path + name */
len = path->len;
if (len && is_dir_sep(path->buf[len - 1]))
len--;
base = len;
while (base && !is_dir_sep(path->buf[base - 1]))
base--;
dirlen = base ? base - 1 : 0;
/* lookup entry for path + name in cache */
fsentry_init(&key[0].u.ent, NULL, path->buf, dirlen);
fsentry_init(&key[1].u.ent, &key[0].u.ent, path->buf + base, len - base);
fse = fscache_get(cache, &key[1].u.ent);
if (!fse)
return mingw_is_mount_point(path);
return fse->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
}
typedef struct fscache_DIR {
struct DIR base_dir; /* extend base struct DIR */
struct fsentry *pfsentry;

Просмотреть файл

@ -22,6 +22,7 @@ void fscache_flush(void);
DIR *fscache_opendir(const char *dir);
int fscache_lstat(const char *file_name, struct stat *buf);
int fscache_is_mount_point(struct strbuf *path);
/* opaque fscache structure */
struct fscache;