core.fsync: new option to harden the index

This commit introduces the new ability for the user to harden the index. In the event of a system crash, the index must be durable for the user to actually find a file that has been added to the repo and then deleted from the working tree. We use the presence of the COMMIT_LOCK flag and absence of the alternate_index_output as a proxy for determining whether we're updating the persistent index of the repo or some temporary index. We don't sync these temporary indexes. Signed-off-by: Neeraj Singh <neerajsi@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Neeraj Singh committed Mar 10, 2022 at 22:43 UTC ba95e96d4c6eed42e30ac3c8b260f4459e3a8575
3 files changed +15 -6
cache.h
+1
@@ -1004,6 +1004,7 @@ enum fsync_component {
1004 FSYNC_COMPONENT_PACK = 1 << 1,
1005 FSYNC_COMPONENT_PACK_METADATA = 1 << 2,
1006 FSYNC_COMPONENT_COMMIT_GRAPH = 1 << 3,
1007 + FSYNC_COMPONENT_INDEX = 1 << 4,
1008 };
1009
1010 #define FSYNC_COMPONENTS_DEFAULT (FSYNC_COMPONENT_PACK | \
config.c
+1
@@ -1331,6 +1331,7 @@ static const struct fsync_component_name {
1331 { "pack", FSYNC_COMPONENT_PACK },
1332 { "pack-metadata", FSYNC_COMPONENT_PACK_METADATA },
1333 { "commit-graph", FSYNC_COMPONENT_COMMIT_GRAPH },
1334 + { "index", FSYNC_COMPONENT_INDEX },
1335 };
1336
1337 static enum fsync_component parse_fsync_components(const char *var, const char *string)
read-cache.c
+13 -6
@@ -2842,7 +2842,7 @@ static int record_ieot(void)
2842 * rely on it.
2843 */
2844 static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2845 - int strip_extensions)
2845 + int strip_extensions, unsigned flags)
2846 {
2847 uint64_t start = getnanotime();
2848 struct hashfile *f;
@@ -2856,6 +2856,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2856 struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
2857 int drop_cache_tree = istate->drop_cache_tree;
2858 off_t offset;
2859 + int csum_fsync_flag;
2860 int ieot_entries = 1;
2861 struct index_entry_offset_table *ieot = NULL;
2862 int nr, nr_threads;
@@ -3089,7 +3090,13 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
3090 return -1;
3091 }
3092
3092 - finalize_hashfile(f, istate->oid.hash, FSYNC_COMPONENT_NONE, CSUM_HASH_IN_STREAM);
3093 + csum_fsync_flag = 0;
3094 + if (!alternate_index_output && (flags & COMMIT_LOCK))
3095 + csum_fsync_flag = CSUM_FSYNC;
3096 +
3097 + finalize_hashfile(f, istate->oid.hash, FSYNC_COMPONENT_INDEX,
3098 + CSUM_HASH_IN_STREAM | csum_fsync_flag);
3099 +
3100 if (close_tempfile_gently(tempfile)) {
3101 error(_("could not close '%s'"), get_tempfile_path(tempfile));
3102 return -1;
@@ -3144,7 +3151,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
3151 */
3152 trace2_region_enter_printf("index", "do_write_index", the_repository,
3153 "%s", get_lock_file_path(lock));
3147 - ret = do_write_index(istate, lock->tempfile, 0);
3154 + ret = do_write_index(istate, lock->tempfile, 0, flags);
3155 trace2_region_leave_printf("index", "do_write_index", the_repository,
3156 "%s", get_lock_file_path(lock));
3157
@@ -3238,7 +3245,7 @@ static int clean_shared_index_files(const char *current_hex)
3245 }
3246
3247 static int write_shared_index(struct index_state *istate,
3241 - struct tempfile **temp)
3248 + struct tempfile **temp, unsigned flags)
3249 {
3250 struct split_index *si = istate->split_index;
3251 int ret, was_full = !istate->sparse_index;
@@ -3248,7 +3255,7 @@ static int write_shared_index(struct index_state *istate,
3255
3256 trace2_region_enter_printf("index", "shared/do_write_index",
3257 the_repository, "%s", get_tempfile_path(*temp));
3251 - ret = do_write_index(si->base, *temp, 1);
3258 + ret = do_write_index(si->base, *temp, 1, flags);
3259 trace2_region_leave_printf("index", "shared/do_write_index",
3260 the_repository, "%s", get_tempfile_path(*temp));
3261
@@ -3357,7 +3364,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
3364 ret = do_write_locked_index(istate, lock, flags);
3365 goto out;
3366 }
3360 - ret = write_shared_index(istate, &temp);
3367 + ret = write_shared_index(istate, &temp, flags);
3368
3369 saved_errno = errno;
3370 if (is_tempfile_active(temp))