Skip to content

fsck: handle packs removed by concurrent repacks - #2221

Open
newren wants to merge 3 commits into
gitgitgadget:masterfrom
newren:en/fsck-pack-race
Open

newren wants to merge 3 commits into
gitgitgadget:masterfrom
newren:en/fsck-pack-race

Conversation

@newren

@newren newren commented Sep 9, 2026

Copy link
Copy Markdown

git fsck and git multi-pack-index verify can race with a concurrent
repack that removes a pack after it has been enumerated. The resulting
errors currently look like corrupt reverse indexes or MIDX entries even
though the objects have safely moved to a replacement pack and a
quiescent retry succeeds.

This series distinguishes pack removal from genuine index corruption
and adds a retry hint when a concurrent repack explains the failure. It
also pins MIDX-referenced packs during verification when they fit within
a conservative file-descriptor budget, eliminating the usual race for
geometrically maintained repositories while preserving the existing
close-as-we-go behavior for unusually large pack sets.

newren added 3 commits October 2, 2026 17:11
"git fsck" enumerates packs up front and later verifies each pack's
reverse index.  If a concurrent "git repack" removes one of those packs
in the meantime, load_pack_revindex_from_disk() fails and fsck reports
"unable to load rev-index", implying corruption.  That is misleading:
the objects are safe in the replacement pack and a retry after
maintenance succeeds.

When the load fails because the ".pack" itself is gone (ENOENT), say so
and suggest retrying once maintenance completes, rather than blaming the
rev-index.  A failure with the pack still present is reported as before,
so genuine corruption still surfaces.

To exercise this race, repeatedly run "git fsck --no-full" while a
concurrent repack replaces existing packs.  Triggering the failure
depends on a pack disappearing between enumeration and opening its
index.

Assisted-by: Claude Opus 4.8
Signed-off-by: Elijah Newren <newren@gmail.com>
"git multi-pack-index verify" (which "git fsck" spawns when MIDX support
is enabled) walks the midx's packs, closing and reopening each by name
as it checks object offsets.  A concurrent "git repack" that unlinks a
redundant pack in that window makes the reopen fail, and verify reports
"failed to load pack in position N", "failed to load pack entry for
oid[N]", or "failed to load pack-index for packfile ..." -- all of which
read like midx corruption even when the objects are still available
in a replacement pack.

A missing referenced ".pack" can be a symptom of concurrent maintenance,
but does not establish whether its objects are available elsewhere.
Add a one-time hint suggesting a retry after maintenance completes,
while keeping the existing per-failure diagnostics and nonzero status.

To provoke it, "git multi-pack-index write" a repo with several packs
and run "git multi-pack-index verify" while "git repack -adq" loops in
the background; verify occasionally fails with one of the messages
above, now followed by the retry hint.

Assisted-by: Claude Opus 4.8
Signed-off-by: Elijah Newren <newren@gmail.com>
MIDX verification closes packs between object groups and later reopens
them by name.  A concurrent repack can remove one in that interval,
causing verification to fail on an otherwise benign race.

When the referenced packs fit within an estimated fd budget, pre-open
them and skip the verifier's per-pack closes during the walk.  Geometric
repacking is expected to keep pack counts small enough for this to be
useful.  Larger MIDX chains retain the close-as-we-go path and its
race-aware diagnostic.

This is best effort: find_lru_pack() ignores do_not_close, so
close_one_pack() may still reclaim descriptors under pressure.

Assisted-by: Claude Opus 4.8
Signed-off-by: Elijah Newren <newren@gmail.com>
@newren
newren force-pushed the en/fsck-pack-race branch from 00926d8 to e717ff2 Compare October 3, 2026 00:14
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