Skip to content

Commit a182516

Browse files
dschodrizzd
authored andcommitted
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 <[email protected]>
1 parent 65bbe70 commit a182516

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

compat/mingw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,6 +2845,8 @@ pid_t waitpid(pid_t pid, int *status, int options)
28452845
return -1;
28462846
}
28472847

2848+
int (*win32_is_mount_point)(struct strbuf *path) = mingw_is_mount_point;
2849+
28482850
int mingw_is_mount_point(struct strbuf *path)
28492851
{
28502852
WIN32_FIND_DATAW findbuf = { 0 };

compat/mingw.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,8 @@ static inline void convert_slashes(char *path)
465465
}
466466
struct strbuf;
467467
int mingw_is_mount_point(struct strbuf *path);
468-
#define is_mount_point mingw_is_mount_point
468+
extern int (*win32_is_mount_point)(struct strbuf *path);
469+
#define is_mount_point win32_is_mount_point
469470
#define CAN_UNLINK_MOUNT_POINTS 1
470471
#define PATH_SEP ';'
471472
extern char *mingw_query_user_email(void);

compat/win32/fscache.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ int fscache_enable(size_t initial_size)
465465
/* redirect opendir and lstat to the fscache implementations */
466466
opendir = fscache_opendir;
467467
lstat = fscache_lstat;
468+
win32_is_mount_point = fscache_is_mount_point;
468469
}
469470
initialized++;
470471
LeaveCriticalSection(&fscache_cs);
@@ -525,6 +526,7 @@ void fscache_disable(void)
525526
/* reset opendir and lstat to the original implementations */
526527
opendir = dirent_opendir;
527528
lstat = mingw_lstat;
529+
win32_is_mount_point = mingw_is_mount_point;
528530
}
529531
LeaveCriticalSection(&fscache_cs);
530532

@@ -592,6 +594,38 @@ int fscache_lstat(const char *filename, struct stat *st)
592594
return 0;
593595
}
594596

597+
/*
598+
* is_mount_point() replacement, uses cache if enabled, otherwise falls
599+
* back to mingw_is_mount_point().
600+
*/
601+
int fscache_is_mount_point(struct strbuf *path)
602+
{
603+
int dirlen, base, len;
604+
struct fsentry key[2], *fse;
605+
struct fscache *cache = fscache_getcache();
606+
607+
if (!cache || !do_fscache_enabled(cache, path->buf))
608+
return mingw_is_mount_point(path);
609+
610+
cache->lstat_requests++;
611+
/* split path into path + name */
612+
len = path->len;
613+
if (len && is_dir_sep(path->buf[len - 1]))
614+
len--;
615+
base = len;
616+
while (base && !is_dir_sep(path->buf[base - 1]))
617+
base--;
618+
dirlen = base ? base - 1 : 0;
619+
620+
/* lookup entry for path + name in cache */
621+
fsentry_init(key, NULL, path->buf, dirlen);
622+
fsentry_init(key + 1, key, path->buf + base, len - base);
623+
fse = fscache_get(cache, key + 1);
624+
if (!fse)
625+
return mingw_is_mount_point(path);
626+
return fse->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
627+
}
628+
595629
typedef struct fscache_DIR {
596630
struct DIR base_dir; /* extend base struct DIR */
597631
struct fsentry *pfsentry;

compat/win32/fscache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ void fscache_flush(void);
2222

2323
DIR *fscache_opendir(const char *dir);
2424
int fscache_lstat(const char *file_name, struct stat *buf);
25+
int fscache_is_mount_point(struct strbuf *path);
2526

2627
/* opaque fscache structure */
2728
struct fscache;

0 commit comments

Comments
 (0)