Merge branch 'jt/object-file-batch-fsync-fix' into seen

When 'core.fsyncMethod' is set to 'batch', the ODB transaction
failed to properly flush large blob packfiles residing in the
temporary directory before migrating the directory's contents to the
main object store.  The execution sequence has been corrected by
performing the packfile flush before the temporary directory
migration, averting failure.

* jt/object-file-batch-fsync-fix:
  object-file: flush transaction packfile before migrating objects
  object-file: lift ODB reprepare out of packfile flush
Junio C Hamano 2026-09-17 12:54:45 -07:00
commit 56f57faa07
2 changed files with 24 additions and 4 deletions

View File

@ -859,8 +859,6 @@ clear_exit:
memset(state, 0, sizeof(*state));

strbuf_release(&packname);
/* Make objects we just wrote available to ourselves */
odb_reprepare(repo->objects);
}

/*
@ -911,8 +909,10 @@ static int odb_transaction_files_write_object_stream(struct odb_transaction *bas
* to zlib compression and is sufficient for this check.
*/
if (state->nr_written && pack_size_limit_cfg &&
pack_size_limit_cfg < state->offset + stream->size)
pack_size_limit_cfg < state->offset + stream->size) {
flush_packfile_transaction(transaction);
odb_reprepare(transaction->base.source->odb);
}

CALLOC_ARRAY(idx, 1);
prepare_packfile_transaction(transaction);
@ -1262,6 +1262,9 @@ static int odb_transaction_files_commit(struct odb_transaction *base)
{
struct odb_transaction_files *transaction =
container_of(base, struct odb_transaction_files, base);
int have_packfile = !!transaction->packfile.f;

flush_packfile_transaction(transaction);

if (transaction->objdir) {
struct strbuf temp_path = STRBUF_INIT;
@ -1293,7 +1296,8 @@ static int odb_transaction_files_commit(struct odb_transaction *base)
transaction->objdir = NULL;
}

flush_packfile_transaction(transaction);
if (have_packfile)
odb_reprepare(transaction->base.source->odb);

return 0;
}

View File

@ -87,6 +87,22 @@ test_expect_success 'add a large file or two' '
test $count = 1
'

test_expect_success 'add large file with loose object in batch fsync' '
test_when_finished "rm -rf batch" &&
git init batch &&

git -C batch config core.bigFileThreshold 5 &&
echo foo >batch/1-small &&
echo foobar >batch/2-large &&

git -C batch -c core.fsync=loose-object -c core.fsyncMethod=batch \
add 1-small 2-large &&

# Neither object may be left behind in a temporary location.
git -C batch cat-file -e :1-small &&
git -C batch cat-file -e :2-large
'

test_expect_success 'checkout a large file' '
large1=$(git rev-parse :large1) &&
git update-index --add --cacheinfo 100644 $large1 another &&