forks: revert to hard-linking objects during gc
commit1613083b89521fb366b254295ea8c8e4c59b727c
authorKyle J. McKay <mackyle@gmail.com>
Sat, 3 Sep 2016 01:08:24 +0000 (2 18:08 -0700)
committerKyle J. McKay <mackyle@gmail.com>
Sat, 3 Sep 2016 01:08:24 +0000 (2 18:08 -0700)
treea5755bb98ae906e4192070fa44cd6174692e6f6d
parent6ddbb9e1ac16ff0a9ec09018af0fe4887d879000
forks: revert to hard-linking objects during gc

In the past we used to hard-link all currently existing packs and loose
objects down to all immediate child forks just before beginning garbage
collection.

This was necessary because we used "git repack -a -d -l" and otherwise
objects no longer referred to by the parent but still reachable by the
child could be lost resulting in child corruption.  And we can't abide
corrupt children.

Subsequently we switched to "git repack -A -d -l" to make sure mail.sh
has time to send out its notifications before any unreachable objects
disappear and to avoid inherent race conditions with simultaneous
pruning and pushing.

Later we took advantage of this change to pack up any remaining (and
therefore unreachable) loose objects after the repack into a single pack
and just hard-link that into all the child forks before running "git
prune".  This is very efficient and works extremely well with one small
exception.

Eventually the child forks will run "git repack -A -d -l" themselves.
Once the parent has finally pruned its unreachable loose objects that
were in the single pack that was hard-linked into all the forks, a fork
running "git repack -A -d -l" will then have any of those unreachable
objects that are also unreachable from the fork pop out of the pack to
become loose objects in the fork.  And they will not be hard-linked
anywhere else when that happens meaning the disk space used could then
be multiplied by the number of forks present.

This is an unacceptable situation and so we must revert to hard-linking
the loose objects themselves into the child forks.  We do, however, skip
hard-linking the packs this time since we are now running repack with
the "-A" option.  We perform the hard-linking just after the repack but
before the "git prune" so we are guaranteed that anything that could
potentially be pruned has already been hard-linked into the child forks
before that happens.

The hard-linking code has also been upgraded to be impervious to command
line length overflow problems when an excessive number of loose objects
are present.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
jobd/gc.sh
toolbox/perform-pre-gc-linking.sh