From bc22d845c4328f5bd896d019b3729f776ad4be4c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 11 Mar 2022 10:58:59 +0100 Subject: core.fsync: new option to harden references When writing both loose and packed references to disk we first create a lockfile, write the updated values into that lockfile, and on commit we rename the file into place. According to filesystem developers, this behaviour is broken because applications should always sync data to disk before doing the final rename to ensure data consistency [1][2][3]. If applications fail to do this correctly, a hard crash of the machine can easily result in corrupted on-disk data. This kind of corruption can in fact be easily observed with Git when the machine hard-resets shortly after writing references to disk. On machines with ext4, this will likely lead to the "empty files" problem: the file has been renamed, but its data has not been synced to disk. The result is that the reference is corrupt, and in the worst case this can lead to data loss. Implement a new option to harden references so that users and admins can avoid this scenario by syncing locked loose and packed references to disk before we rename them into place. [1]: https://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ [2]: https://btrfs.wiki.kernel.org/index.php/FAQ (What are the crash guarantees of overwrite-by-rename) [3]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/ext4.rst (see auto_da_alloc) Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- cache.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'cache.h') diff --git a/cache.h b/cache.h index cde0900d05..033e5b0779 100644 --- a/cache.h +++ b/cache.h @@ -1005,6 +1005,7 @@ enum fsync_component { FSYNC_COMPONENT_PACK_METADATA = 1 << 2, FSYNC_COMPONENT_COMMIT_GRAPH = 1 << 3, FSYNC_COMPONENT_INDEX = 1 << 4, + FSYNC_COMPONENT_REFERENCE = 1 << 5, }; #define FSYNC_COMPONENTS_OBJECTS (FSYNC_COMPONENT_LOOSE_OBJECT | \ @@ -1017,7 +1018,8 @@ enum fsync_component { FSYNC_COMPONENTS_DERIVED_METADATA | \ ~FSYNC_COMPONENT_LOOSE_OBJECT) -#define FSYNC_COMPONENTS_COMMITTED (FSYNC_COMPONENTS_OBJECTS) +#define FSYNC_COMPONENTS_COMMITTED (FSYNC_COMPONENTS_OBJECTS | \ + FSYNC_COMPONENT_REFERENCE) #define FSYNC_COMPONENTS_ADDED (FSYNC_COMPONENTS_COMMITTED | \ FSYNC_COMPONENT_INDEX) @@ -1026,7 +1028,8 @@ enum fsync_component { FSYNC_COMPONENT_PACK | \ FSYNC_COMPONENT_PACK_METADATA | \ FSYNC_COMPONENT_COMMIT_GRAPH | \ - FSYNC_COMPONENT_INDEX) + FSYNC_COMPONENT_INDEX | \ + FSYNC_COMPONENT_REFERENCE) /* * A bitmask indicating which components of the repo should be fsynced. -- cgit v1.2.3