From: Patrick Steinhardt Date: Wed, 19 Aug 2026 08:24:07 GMT Subject: Re: [PATCH v3 3/3] core: convert build-time USE_NSEC into runtime core.useNanosec Message-ID: In-Reply-To: <48fceb4b575ca39346cf2f59f621584a19049008.1787065125.git.ben.knoble@gmail.com> On Tue, Aug 18, 2026 at 10:59:47AM -0400, D. Ben Knoble wrote: > Racy Git problems persist today, manifesting themselves in the > performance of commands like "git diff" in new worktrees [1]. We have > long had a build knob "USE_NSEC" to tell Git to use in-core nanosecond > precision when available, which mitigates most if not all racy issues, > but most builds we know about it don't use it. In part, that's because s/about it/about/ > diff --git a/Documentation/config/core.adoc b/Documentation/config/core.adoc > index 340329edc3..33104444ab 100644 > --- a/Documentation/config/core.adoc > +++ b/Documentation/config/core.adoc > @@ -118,6 +118,12 @@ core.trustctime:: > crawlers and some backup systems). > See linkgit:git-update-index[1]. True by default. > > +core.useNanosec:: > + If true, use nanosecond precision for ctime and mtime > + comparisions between the index and the working tree (if Git > + was compiled to store it). > + See link:technical/racy-git.html[Racy Git]. False by default. Should we mentino here that this may not be safe on all platforms and/or filesystems, in addition to linking to racy-hit? And do we really want to link to the HTML page here? The user may be reading a manpage, so doing so feels a bit weird to me. > diff --git a/environment.c b/environment.c > index 6676e6f5ae..c7f6b801f4 100644 > --- a/environment.c > +++ b/environment.c > @@ -571,6 +571,13 @@ int git_default_core_config(const char *var, const char *value, > return 0; > } > > +#ifndef NO_NSEC > + if (!strcmp(var, "core.usenanosec")) { > + cfg->use_nanosec = git_config_bool(var, value); > + return 0; > + } > +#endif Do we want to omit a warning in case the config is enabled and we have NO_SEC set? Or would that be too obnoxious? > @@ -769,6 +776,9 @@ void repo_config_values_init(struct repo_config_values *cfg) > cfg->ignore_case = 0; > cfg->trust_executable_bit = 1; > cfg->has_symlinks = platform_has_symlinks(); > +#ifndef NO_NSEC > + cfg->use_nanosec = 0; > +#endif Can't we set this unconditionally? The respective field exists unconditionally, too. > diff --git a/read-cache.c b/read-cache.c > index 6c449f393d..31888f77ee 100644 > --- a/read-cache.c > +++ b/read-cache.c > @@ -353,12 +353,18 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st) > static int is_racy_stat(const struct index_state *istate, > const struct stat_data *sd) > { > +#ifndef NO_NSEC > + int use_nsec = repo_config_values(istate->repo)->use_nanosec; > +#endif > + > return (istate->timestamp.sec && > -#ifdef USE_NSEC > - /* nanosecond timestamped files can also be racy! */ > - (istate->timestamp.sec < sd->sd_mtime.sec || > - (istate->timestamp.sec == sd->sd_mtime.sec && > - istate->timestamp.nsec <= sd->sd_mtime.nsec)) > +#ifndef NO_NSEC > + /* nanosecond timestamped files can also be racy! */ > + use_nsec > + ? (istate->timestamp.sec < sd->sd_mtime.sec || > + (istate->timestamp.sec == sd->sd_mtime.sec && > + istate->timestamp.nsec <= sd->sd_mtime.nsec)) > + : istate->timestamp.sec <= sd->sd_mtime.sec > #else > istate->timestamp.sec <= sd->sd_mtime.sec > #endif I think this would be a bit more readable if we had a single NO_NSEC block. > diff --git a/statinfo.c b/statinfo.c > index 5e00af127d..2f2cec6282 100644 > --- a/statinfo.c > +++ b/statinfo.c > @@ -72,12 +72,14 @@ int match_stat_data(const struct stat_data *sd, struct stat *st) > sd->sd_ctime.sec != (unsigned int)st->st_ctime) > changed |= CTIME_CHANGED; > > -#ifdef USE_NSEC > - if (cfg->check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st)) > - changed |= MTIME_CHANGED; > - if (cfg->trust_ctime && cfg->check_stat && > - sd->sd_ctime.nsec != ST_CTIME_NSEC(*st)) > - changed |= CTIME_CHANGED; > +#ifndef NO_NSEC > + if (cfg->use_nanosec) { > + if (cfg->check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st)) > + changed |= MTIME_CHANGED; > + if (cfg->trust_ctime && cfg->check_stat && > + sd->sd_ctime.nsec != ST_CTIME_NSEC(*st)) > + changed |= CTIME_CHANGED; > + } > #endif There's one more site in "builtin/update-index.c" where we mention USE_NSEC that wasn't updated as part of this patch. Thanks! Patrick