Skip to content

Commit ac181a3

Browse files
committed
cat-file: snapshot pack indexes before enumerating all objects
The previous commit made "git cat-file --batch-all-objects" error out when a concurrent repack removes a pack mid-walk. That is correct but pessimistic on servers that repack often. Reduce how often it triggers by opening every pack index up front, before the walk. An index mmap survives unlink() of the .idx and pack fd pressure (close_one_pack() closes only the pack fd), so the object set is fixed once the indexes are open. For --batch-all-objects this adds no work: the walk opens every index anyway. Like f6b2625 (fsck: snapshot default refs before object walk, 2026-01-09), this narrows rather than closes the race; the residue is still caught by the previous commit rather than silently dropped. Assisted-by: Claude Opus 4.8 Signed-off-by: Elijah Newren <newren@gmail.com>
1 parent 5591ca7 commit ac181a3

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

‎builtin/cat-file.c‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,23 @@ static int batch_one_object_oi(const struct object_id *oid,
10171017
return payload->callback(oid, NULL, 0, payload->payload);
10181018
}
10191019

1020+
/*
1021+
* Open every pack index up front so the enumeration's object set is
1022+
* fixed: an index mmap survives unlink() of the .idx and pack fd
1023+
* pressure (close_one_pack() closes only the pack fd). This narrows
1024+
* the race with concurrent repacks, like f6b262581a88 (fsck: snapshot
1025+
* default refs before object walk, 2026-01-09).
1026+
*/
1027+
static int snapshot_pack_indexes(void)
1028+
{
1029+
struct packed_git *p;
1030+
1031+
repo_for_each_pack(the_repository, p)
1032+
if (open_pack_index(p))
1033+
return -1;
1034+
return 0;
1035+
}
1036+
10201037
static int batch_each_object(struct batch_options *opt,
10211038
for_each_object_fn callback,
10221039
unsigned flags,
@@ -1084,6 +1101,11 @@ static int batch_objects(struct batch_options *opt)
10841101

10851102
disable_replace_refs();
10861103

1104+
if (snapshot_pack_indexes()) {
1105+
strbuf_release(&output);
1106+
return error(_("unable to enumerate all objects"));
1107+
}
1108+
10871109
cb.opt = opt;
10881110
cb.expand = &data;
10891111
cb.scratch = &output;

0 commit comments

Comments
 (0)