Skip to content

Commit 835c030

Browse files
committed
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>
1 parent eaf317c commit 835c030

File tree

4 files changed

+40
-1
lines changed

4 files changed

+40
-1
lines changed

compat/mingw.c

+2
Original file line numberDiff line numberDiff line change
@@ -3017,6 +3017,8 @@ pid_t waitpid(pid_t pid, int *status, int options)
30173017
return -1;
30183018
}
30193019

3020+
int (*win32_is_mount_point)(struct strbuf *path) = mingw_is_mount_point;
3021+
30203022
int mingw_is_mount_point(struct strbuf *path)
30213023
{
30223024
WIN32_FIND_DATAW findbuf = { 0 };

compat/mingw.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ static inline void convert_slashes(char *path)
481481
}
482482
struct strbuf;
483483
int mingw_is_mount_point(struct strbuf *path);
484-
#define is_mount_point mingw_is_mount_point
484+
extern int (*win32_is_mount_point)(struct strbuf *path);
485+
#define is_mount_point win32_is_mount_point
485486
#define CAN_UNLINK_MOUNT_POINTS 1
486487
#define PATH_SEP ';'
487488
char *mingw_query_user_email(void);

compat/win32/fscache.c

+35
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ int fscache_enable(size_t initial_size)
469469
/* redirect opendir and lstat to the fscache implementations */
470470
opendir = fscache_opendir;
471471
lstat = fscache_lstat;
472+
win32_is_mount_point = fscache_is_mount_point;
472473
}
473474
initialized++;
474475
LeaveCriticalSection(&fscache_cs);
@@ -529,6 +530,7 @@ void fscache_disable(void)
529530
/* reset opendir and lstat to the original implementations */
530531
opendir = dirent_opendir;
531532
lstat = mingw_lstat;
533+
win32_is_mount_point = mingw_is_mount_point;
532534
}
533535
LeaveCriticalSection(&fscache_cs);
534536

@@ -599,6 +601,39 @@ int fscache_lstat(const char *filename, struct stat *st)
599601
return 0;
600602
}
601603

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

compat/win32/fscache.h

+1
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)