Skip to content

Commit fef2a72

Browse files
bk2204gitster
authored andcommitted
fsck: do not loop infinitely when processing packs
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 67ad421 commit fef2a72

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

packfile.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *stor
183183
struct repo_for_each_pack_data {
184184
struct odb_source *source;
185185
struct packfile_list_entry *entry;
186+
struct repository *repo;
186187
};
187188

188189
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
191192

192193
odb_prepare_alternates(repo->objects);
193194

195+
data.repo = repo;
196+
194197
for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
195-
struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
198+
struct packfile_list_entry *entry;
199+
200+
source->packfiles->skip_mru_updates = true;
201+
entry = packfile_store_get_packs(source->packfiles);
196202
if (!entry)
197203
continue;
198204
data.source = source;
@@ -212,14 +218,20 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
212218
return;
213219

214220
for (source = data->source->next; source; source = source->next) {
215-
struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
221+
struct packfile_list_entry *entry;
222+
223+
source->packfiles->skip_mru_updates = true;
224+
entry = packfile_store_get_packs(source->packfiles);
216225
if (!entry)
217226
continue;
218227
data->source = source;
219228
data->entry = entry;
220229
return;
221230
}
222231

232+
for (struct odb_source *source = data->repo->objects->sources; source; source = source->next)
233+
source->packfiles->skip_mru_updates = false;
234+
223235
data->source = NULL;
224236
data->entry = NULL;
225237
}

t/t1050-large.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ test_expect_success 'hash-object' '
160160
git hash-object large1
161161
'
162162

163+
test_expect_success 'fsck does not loop forever' '
164+
git fsck
165+
'
166+
163167
test_expect_success 'cat-file a large file' '
164168
git cat-file blob :large1 >/dev/null
165169
'

0 commit comments

Comments
 (0)