diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-04-26 09:10:00 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-04-26 11:14:22 +0300 |
commit | c89c8002131dabee677cce9c0551801a8e272570 (patch) | |
tree | 1f1ade01373f5918534e2182688da96bdd5c40fc | |
parent | e1f0e5a5ffc31387cb1137c41db538f22e0153de (diff) |
git: Fix corruption of refs on hard-resetspks-git-core.fsync-compatibility
In the past, we had several incidents where repositories ended up with
corrupted loose references immediately after a server was experiencing a
hard shut-down. The root cause of this is that Git historically didn't
flush the contents of loose references to disk before renaming them into
place. This usage is explicitly documented to be invalid by various
filesystems in the Linux kernel. Most importantly, documentation of the
ext4 filesystem says that:
Many broken applications don't use fsync() when replacing existing
files via patterns such as fd = open("foo.new")/write(fd,..)/close(fd)/
rename("foo.new", "foo"), or worse yet, fd = open("foo",
O_TRUNC)/write(fd,..)/close(fd).
With Git v2.36.0 new infrastructure was introduced that provides finer
grained control of exactly what data should be flushed to disk via the
new `core.fsync` option. As part of that effort we have also upstreamed
patches which give us the ability to also flush references to disk
before they're renamed into place.
So let's finally fix this source of corruption on newer Git versions by
enabling fsync(3P) for references.
Changelog: fixed
-rw-r--r-- | internal/git/command_factory.go | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/internal/git/command_factory.go b/internal/git/command_factory.go index a328e1415..a9544a46c 100644 --- a/internal/git/command_factory.go +++ b/internal/git/command_factory.go @@ -465,10 +465,10 @@ func (cf *ExecCommandFactory) combineArgs(ctx context.Context, gitConfig []confi if gitVersion.HasGranularFsyncConfig() { combinedGlobals = append( combinedGlobals, - // For now, we only fsync what Git versions previous to v2.36.0 have fsynced - // when `core.fsyncObjectFiles=true`. Later, we'll want to expand this to - // also sync references to disk to fix a long-standing issue. - ConfigPair{Key: "core.fsync", Value: "objects,derived-metadata"}, + // This is the same as below, but in addition we're also syncing packed-refs + // and loose refs to disk. This fixes a long-standing issue we've had where + // hard reboots of a server could end up corrupting loose references. + ConfigPair{Key: "core.fsync", Value: "objects,derived-metadata,reference"}, ConfigPair{Key: "core.fsyncMethod", Value: "fsync"}, ) } else { |