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>
							parent
							
								
									6f1dc21d98
								
							
						
					
					
						commit
						3bd28eb299
					
				
							
								
								
									
										20
									
								
								fsmonitor.c
								
								
								
								
							
							
						
						
									
										20
									
								
								fsmonitor.c
								
								
								
								
							|  | @ -54,12 +54,19 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data, | ||||||
| 	return 0; | 	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) | void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) | ||||||
| { | { | ||||||
| 	uint32_t hdr_version; | 	uint32_t hdr_version; | ||||||
| 	uint64_t tm; | 	uint64_t tm; | ||||||
| 	struct ewah_bitmap *bitmap; |  | ||||||
| 	int i; |  | ||||||
| 	uint32_t ewah_start; | 	uint32_t ewah_start; | ||||||
| 	uint32_t ewah_size = 0; | 	uint32_t ewah_size = 0; | ||||||
| 	int fixup = 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 */ | 	strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */ | ||||||
|  |  | ||||||
| 	ewah_start = sb->len; | 	ewah_start = sb->len; | ||||||
| 	bitmap = ewah_new(); | 	ewah_serialize_strbuf(istate->fsmonitor_dirty, sb); | ||||||
| 	for (i = 0; i < istate->cache_nr; i++) | 	ewah_free(istate->fsmonitor_dirty); | ||||||
| 		if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) | 	istate->fsmonitor_dirty = NULL; | ||||||
| 			ewah_set(bitmap, i); |  | ||||||
| 	ewah_serialize_strbuf(bitmap, sb); |  | ||||||
| 	ewah_free(bitmap); |  | ||||||
|  |  | ||||||
| 	/* fix up size field */ | 	/* fix up size field */ | ||||||
| 	put_be32(&ewah_size, sb->len - ewah_start); | 	put_be32(&ewah_size, sb->len - ewah_start); | ||||||
|  |  | ||||||
|  | @ -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); | 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); | extern void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -2525,6 +2525,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, | ||||||
| 	int new_shared_index, ret; | 	int new_shared_index, ret; | ||||||
| 	struct split_index *si = istate->split_index; | 	struct split_index *si = istate->split_index; | ||||||
|  |  | ||||||
|  | 	if (istate->fsmonitor_last_update) | ||||||
|  | 		fill_fsmonitor_bitmap(istate); | ||||||
|  |  | ||||||
| 	if (!si || alternate_index_output || | 	if (!si || alternate_index_output || | ||||||
| 	    (istate->cache_changed & ~EXTMASK)) { | 	    (istate->cache_changed & ~EXTMASK)) { | ||||||
| 		if (si) | 		if (si) | ||||||
|  |  | ||||||
|  | @ -301,4 +301,17 @@ do | ||||||
| 	done | 	done | ||||||
| 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 | test_done | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Alex Vandiver
						Alex Vandiver