Skip to content

entry: fix fscache stale directory listing in parallel checkout pathspec#917

Open
tyrielv wants to merge 1 commit into
microsoft:vfs-2.53.0from
tyrielv:tyrielv/fscache-parallel-checkout-fix
Open

entry: fix fscache stale directory listing in parallel checkout pathspec#917
tyrielv wants to merge 1 commit into
microsoft:vfs-2.53.0from
tyrielv:tyrielv/fscache-parallel-checkout-fix

Conversation

@tyrielv

@tyrielv tyrielv commented May 15, 2026

Copy link
Copy Markdown
  • This is an early version of work already under review upstream.

Upstream PR: git-for-windows#6250

Problem

git checkout <tree> -- <pathspec> with checkout.workers > 1 and core.fscache=true (Windows) fails when restoring files into directories that do not yet exist on disk. Two failure modes:

  1. fatal: cannot create directory at '...': Directory not empty (exit 128)
  2. error: unable to stat just-written file '...' (exit 255)

100% reproducible when two or more files share a not-yet-created parent directory.

Root Cause

The Windows fscache caches directory listings that become stale when create_directories() creates new parent directories via mkdir() or when write_pc_item() writes new files. With workers=1, write_entry() calls flush_fscache() after each file, keeping the cache in sync. With workers>1, enqueue_checkout() defers the write (and the flush), leaving the cache stale for subsequent entries.

Fix

Add flush_fscache() calls:

  • In create_directories() after each successful mkdir(), so has_dirs_only_path() sees the new directory
  • In write_pc_item() before lstat() of the just-written file

On non-Windows platforms flush_fscache() is a no-op.

Test

Adds a regression test to t2080-parallel-checkout-basics.sh (MINGW prereq) that deterministically reproduces the bug: two files sharing a nested parent directory, deleted in a second commit, then restored via git checkout <tree> -- <pathspec> with workers=2.

CI confirmed the test fails without the fix.

@tyrielv tyrielv force-pushed the tyrielv/fscache-parallel-checkout-fix branch 3 times, most recently from 8b819f9 to b134fd2 Compare May 18, 2026 16:51
@tyrielv tyrielv marked this pull request as ready for review May 18, 2026 17:08
When checkout.workers > 1 and core.fscache is enabled on Windows,
'git checkout <tree> -- <pathspec>' fails when restoring files into
directories that do not yet exist on disk. Two failure modes occur:

1. create_directories(): the fscache returns a stale directory listing
   that does not include a just-created directory. has_dirs_only_path()
   reports it as non-existent, triggering the unlink+mkdir recovery
   path which fails with 'cannot create directory: Directory not empty'.

2. write_pc_item(): after writing and closing a file, lstat() cannot
   see it through the stale fscache, failing with 'unable to stat
   just-written file'.

With workers=1, write_entry() calls flush_fscache() after each file,
keeping the cache in sync. With workers>1, enqueue_checkout() defers
the write (and the flush), leaving the cache stale for subsequent
entries.

Fix both by adding flush_fscache() calls after mkdir() in
create_directories() and before lstat() in write_pc_item(). On
non-Windows platforms flush_fscache() is a no-op.

Assisted-by: Claude Opus 4.6
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
@tyrielv tyrielv force-pushed the tyrielv/fscache-parallel-checkout-fix branch from b134fd2 to 1d637ef Compare May 18, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant