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
Copy link
Copy Markdown

@tyrielv tyrielv commented May 15, 2026

  • 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.

Bug: https://dev.azure.com/microsoft/OS/_workitems/edit/62260193

@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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant