From: "brian m. carlson" <sandals@crustytoothpaste•net>
To: <git@vger•kernel.org>
Cc: Junio C Hamano <gitster@pobox•com>, Patrick Steinhardt <ps@pks•im>
Subject: [PATCH] fsck: do not loop infinitely when processing packs
Date: Sun, 22 Feb 2026 18:37:10 +0000 [thread overview]
Message-ID: <20260222183710.2963424-1-sandals@crustytoothpaste.net> (raw)
When we iterate over our packfiles in the fsck code, we do so twice.
The first time, we count the number of objects in all of the packs
together and later on, we iterate a second time, processing each pack
and verifying its integrity.
This would normally work fine, but if we have two packs and we're
processing the second, the verification process will open the pack to
read from it, which will place it at the beginning of the most recently
used list. Since this same list is used for iteration, the pack we most
recently processed before this will then be behind the current pack in
the linked list, so when we next process the list, we will go back to
the first pack again and then loop forever. This also makes our
progress indicator loop up to many thousands of percent, which is not
only nonsensical, but a clear indication that something has gone wrong.
Solve this by skipping our MRU updates when we're iterating over
packfiles, which avoids the reordering that causes problems.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste•net>
---
I realize that t1050 may seem like a bizarre place to put this test.
However, I was debugging my sha256-interop branch and why the final test
calling `git fsck` was failing, so I placed a `git fsck` earlier in the
test to double-check and discovered the problem. Since we already have
a natural testcase here, I thought I'd just place the test where we
already know it will trigger the problem.
packfile.h | 16 ++++++++++++++--
t/t1050-large.sh | 4 ++++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/packfile.h b/packfile.h
index acc5c55ad5..086d98c1a0 100644
--- a/packfile.h
+++ b/packfile.h
@@ -183,6 +183,7 @@ struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *stor
struct repo_for_each_pack_data {
struct odb_source *source;
struct packfile_list_entry *entry;
+ struct repository *repo;
};
static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct repository *repo)
@@ -191,8 +192,13 @@ static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct
odb_prepare_alternates(repo->objects);
+ data.repo = repo;
+
for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
- struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
+ struct packfile_list_entry *entry;
+
+ source->packfiles->skip_mru_updates = true;
+ entry = packfile_store_get_packs(source->packfiles);
if (!entry)
continue;
data.source = source;
@@ -212,7 +218,10 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
return;
for (source = data->source->next; source; source = source->next) {
- struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
+ struct packfile_list_entry *entry;
+
+ source->packfiles->skip_mru_updates = true;
+ entry = packfile_store_get_packs(source->packfiles);
if (!entry)
continue;
data->source = source;
@@ -220,6 +229,9 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
return;
}
+ for (struct odb_source *source = data->repo->objects->sources; source; source = source->next)
+ source->packfiles->skip_mru_updates = false;
+
data->source = NULL;
data->entry = NULL;
}
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 5be273611a..75e75e627c 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -160,6 +160,10 @@ test_expect_success 'hash-object' '
git hash-object large1
'
+test_expect_success 'fsck does not loop forever' '
+ git fsck
+'
+
test_expect_success 'cat-file a large file' '
git cat-file blob :large1 >/dev/null
'
next reply other threads:[~2026-02-22 18:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-22 18:37 brian m. carlson [this message]
2026-02-22 22:39 ` [PATCH] fsck: do not loop infinitely when processing packs Junio C Hamano
2026-02-22 23:07 ` brian m. carlson
2026-02-23 7:12 ` Jeff King
2026-02-23 8:46 ` Patrick Steinhardt
2026-02-23 9:25 ` Jeff King
2026-02-23 9:36 ` Patrick Steinhardt
2026-02-23 9:46 ` Jeff King
2026-02-23 15:49 ` Junio C Hamano
2026-02-23 8:43 ` Patrick Steinhardt
2026-02-23 9:27 ` Jeff King
2026-02-23 9:53 ` Patrick Steinhardt
2026-02-24 22:23 ` brian m. carlson
2026-02-24 22:32 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260222183710.2963424-1-sandals@crustytoothpaste.net \
--to=sandals@crustytoothpaste$(echo .)net \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
--cc=ps@pks$(echo .)im \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox