From 3bd28eb29912801481b293691039b05caebf13a3 Mon Sep 17 00:00:00 2001 From: Alex Vandiver Date: Thu, 9 Nov 2017 11:58:10 -0800 Subject: [PATCH] fsmonitor: store fsmonitor bitmap before splitting index ba1b9cac ("fsmonitor: delay updating state until after split index is merged", 2017-10-27) resolved the problem of the fsmonitor data being applied to the non-base index when reading; however, a similar problem exists when writing the index. Specifically, writing of the fsmonitor extension happens only after the work to split the index has been applied -- as such, the information in the index is only for the non-"base" index, and thus the extension information contains only partial data. When saving, compute the ewah bitmap before the index is split, and store it in the fsmonitor_dirty field, mirroring the behavior that occurred during reading. fsmonitor_dirty is kept from being leaked by being freed when the extension data is written -- which always happens precisely once, no matter the split index configuration. Signed-off-by: Alex Vandiver Signed-off-by: Junio C Hamano --- fsmonitor.c | 20 ++++++++++++-------- fsmonitor.h | 9 ++++++++- read-cache.c | 3 +++ t/t7519-status-fsmonitor.sh | 13 +++++++++++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/fsmonitor.c b/fsmonitor.c index f494a866d5..0af7c4edba 100644 --- a/fsmonitor.c +++ b/fsmonitor.c @@ -54,12 +54,19 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data, return 0; } +void fill_fsmonitor_bitmap(struct index_state *istate) +{ + int i; + istate->fsmonitor_dirty = ewah_new(); + for (i = 0; i < istate->cache_nr; i++) + if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) + ewah_set(istate->fsmonitor_dirty, i); +} + void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) { uint32_t hdr_version; uint64_t tm; - struct ewah_bitmap *bitmap; - int i; uint32_t ewah_start; uint32_t ewah_size = 0; int fixup = 0; @@ -73,12 +80,9 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */ ewah_start = sb->len; - bitmap = ewah_new(); - for (i = 0; i < istate->cache_nr; i++) - if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) - ewah_set(bitmap, i); - ewah_serialize_strbuf(bitmap, sb); - ewah_free(bitmap); + ewah_serialize_strbuf(istate->fsmonitor_dirty, sb); + ewah_free(istate->fsmonitor_dirty); + istate->fsmonitor_dirty = NULL; /* fix up size field */ put_be32(&ewah_size, sb->len - ewah_start); diff --git a/fsmonitor.h b/fsmonitor.h index 0de644e01a..cd3cc0ccf2 100644 --- a/fsmonitor.h +++ b/fsmonitor.h @@ -10,7 +10,14 @@ extern struct trace_key trace_fsmonitor; extern int read_fsmonitor_extension(struct index_state *istate, const void *data, unsigned long sz); /* - * Write the CE_FSMONITOR_VALID state into the fsmonitor index extension. + * Fill the fsmonitor_dirty ewah bits with their state from the index, + * before it is split during writing. + */ +extern void fill_fsmonitor_bitmap(struct index_state *istate); + +/* + * Write the CE_FSMONITOR_VALID state into the fsmonitor index + * extension. Reads from the fsmonitor_dirty ewah in the index. */ extern void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate); diff --git a/read-cache.c b/read-cache.c index 05c0a33fdd..0724ea8c9b 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2525,6 +2525,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, int new_shared_index, ret; struct split_index *si = istate->split_index; + if (istate->fsmonitor_last_update) + fill_fsmonitor_bitmap(istate); + if (!si || alternate_index_output || (istate->cache_changed & ~EXTMASK)) { if (si) diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index c6df85af5e..eb2d13bbcf 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -301,4 +301,17 @@ do done done +# test that splitting the index dosn't interfere +test_expect_success 'splitting the index results in the same state' ' + write_integration_script && + dirty_repo && + git update-index --fsmonitor && + git ls-files -f >expect && + test-dump-fsmonitor >&2 && echo && + git update-index --fsmonitor --split-index && + test-dump-fsmonitor >&2 && echo && + git ls-files -f >actual && + test_cmp expect actual +' + test_done