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 <alexmv@dropbox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Alex Vandiver committed Nov 9, 2017 at 11:58 UTC 3bd28eb29912801481b293691039b05caebf13a3
4 files changed +36 -9
fsmonitor.c
+12 -8
@@ -54,12 +54,19 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data,
54 return 0;
55 }
56
57 +void fill_fsmonitor_bitmap(struct index_state *istate)
58 +{
59 + int i;
60 + istate->fsmonitor_dirty = ewah_new();
61 + for (i = 0; i < istate->cache_nr; i++)
62 + if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
63 + ewah_set(istate->fsmonitor_dirty, i);
64 +}
65 +
66 void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
67 {
68 uint32_t hdr_version;
69 uint64_t tm;
61 - struct ewah_bitmap *bitmap;
62 - int i;
70 uint32_t ewah_start;
71 uint32_t ewah_size = 0;
72 int fixup = 0;
@@ -73,12 +80,9 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
80 strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
81
82 ewah_start = sb->len;
76 - bitmap = ewah_new();
77 - for (i = 0; i < istate->cache_nr; i++)
78 - if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
79 - ewah_set(bitmap, i);
80 - ewah_serialize_strbuf(bitmap, sb);
81 - ewah_free(bitmap);
83 + ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
84 + ewah_free(istate->fsmonitor_dirty);
85 + istate->fsmonitor_dirty = NULL;
86
87 /* fix up size field */
88 put_be32(&ewah_size, sb->len - ewah_start);
fsmonitor.h
+8 -1
@@ -10,7 +10,14 @@ extern struct trace_key trace_fsmonitor;
10 extern int read_fsmonitor_extension(struct index_state *istate, const void *data, unsigned long sz);
11
12 /*
13 - * Write the CE_FSMONITOR_VALID state into the fsmonitor index extension.
13 + * Fill the fsmonitor_dirty ewah bits with their state from the index,
14 + * before it is split during writing.
15 + */
16 +extern void fill_fsmonitor_bitmap(struct index_state *istate);
17 +
18 +/*
19 + * Write the CE_FSMONITOR_VALID state into the fsmonitor index
20 + * extension. Reads from the fsmonitor_dirty ewah in the index.
21 */
22 extern void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate);
23
read-cache.c
+3
@@ -2525,6 +2525,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
2525 int new_shared_index, ret;
2526 struct split_index *si = istate->split_index;
2527
2528 + if (istate->fsmonitor_last_update)
2529 + fill_fsmonitor_bitmap(istate);
2530 +
2531 if (!si || alternate_index_output ||
2532 (istate->cache_changed & ~EXTMASK)) {
2533 if (si)
t/t7519-status-fsmonitor.sh
+13
@@ -301,4 +301,17 @@ do
301 done
302 done
303
304 +# test that splitting the index dosn't interfere
305 +test_expect_success 'splitting the index results in the same state' '
306 + write_integration_script &&
307 + dirty_repo &&
308 + git update-index --fsmonitor &&
309 + git ls-files -f >expect &&
310 + test-dump-fsmonitor >&2 && echo &&
311 + git update-index --fsmonitor --split-index &&
312 + test-dump-fsmonitor >&2 && echo &&
313 + git ls-files -f >actual &&
314 + test_cmp expect actual
315 +'
316 +
317 test_done