git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] update-index: refresh should rewrite index in case of racy timestamps

From
Marc Strapetz <marc.strapetz@syntevo.com>
Date
Dec 23, 2021, 18:24 UTC
Message-ID
<b97672fa-837f-1e28-f7f2-aee80e52d374@syntevo.com>
In-Reply-To
<xmqqfsqkdwo4.fsf@gitster.g>
On 23/12/2021 00:52, Junio C Hamano wrote:
Show 17 quoted lines
> Ah, there are cases where we do clear active_cache_changed when we
> notice that an operation detected an error, to avoid spreading the
> breakage by writing the index file out, and I think that is the
> right thing to do.  Which means that the above patch is not quite
> right.  Perhaps taking all of the above together, something like
> this?
> 
> 	*o->has_errors |= refresh_cache(o->flags | flag);
> 	if (*o->has_errors)
> 		active_cache_changed = 0;
> 	else if (has_racy_timestamps(&the_index))
>          	/*
> 		 * Even if nothing else has changed, updating the file
> 		 * increases the chance that racy timestamps become
> 		 * non-racy, helping future run-time performance.
> 		 */
> 		active_cache_changed |= SOMETHING_CHANGED;

I think it's safe to write the index even if refresh_cache() reports an "error" and we should actually do that:

The underlying refresh_index() will report an "error" only for "file: needs merge" and "file: needs update". In both cases, the corresponding entries will not have been updated. Every entry which has been updated is good on its own and writing these updates makes the index a little bit better. Subsequent calls to refresh_index() won't have to do the same work again (like invoking the quite expensive LFS filter).

This is also how cmd_status() currently works: it does not pay attention to the return value of refresh_index() and will always write the index if racy timestamps are encountered.

Overall, the "error" handling in update-index.c might not always do what one expects. Let's consider your suggested fix. When invoking:

update-index --refresh
this won't fix racy timestamps, however:
update-index --refresh --add untracked

will do. I think this is caused by active_cache_changed being used in two different ways: to indicate that the cache should be written and to indicate that it must not be written. It might be a good idea to take the latter "block index write" to a separate static variable in update-index.c.

Candidate usages of this new "block index write" variable will be in the existing callbacks: errors detected in unresolve_callback() should probably continue to block an index write, to ensure that either all or none of the specified files will be unresolved. For the reupdate_callback(), the underlying do_reupdate() seems to return 0 always, so there is dead code in the callback (or am I completely blind?). To stay on the safe side, we may still continue to block an index write here. The refresh_callback() will never block an index write.

Does it make sense to clarify error handling in some preceding commit and only then address the razy timestamps? It will probably make this second commit clearer.

Show 14 quoted lines
>> +}
>> +
>> +update_assert_changed() {
>> +	local ts1=$(test-tool chmtime --get .git/index) &&
>> +	test_might_fail git update-index $1 &&
>> +	local ts2=$(test-tool chmtime --get .git/index) &&
>> +	[ $ts1 -ne $ts2 ]
>> +}
>> +
>> +test_expect_success 'setup' '
>> +	touch .git/fs-tstamp &&
> 
> Not that it is wrong, but do we need to create such a throw-away
> file inside the .git directory?

We actually only need a timestamp for which we know that it is before the timestamp the next file system operation would create. I agree that it should be easy to rewrite that using "test-tool chmtime". This should also simplify reset_mtime().

Regarding all other comments, thanks, I'll address them as suggested for the next patch. And sorry for not checking CodingGuidelines before (I had completely missed this document).

-Marc
Previous: Junio C HamanoNext: Marc Strapetz via GitGitGadget
Message 3 of 20 in “update-index: refresh should rewrite index in case of racy timestamps”
  1. update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Dec 22, 2021
  2. Junio C HamanoDec 22, 2021
  3. Marc StrapetzDec 23, 2021
  4. 0/2 update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Jan 5, 2022
  5. 1/2 t7508: add tests capturing racy timestamp handlingMarc Strapetz via GitGitGadget, Jan 5, 2022
  6. Junio C HamanoJan 5, 2022
  7. Marc StrapetzJan 6, 2022
  8. 2/2 update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Jan 5, 2022
  9. Junio C HamanoJan 5, 2022
  10. 0/4 update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Jan 6, 2022
  11. 1/4 test-lib: introduce API for verifying file mtimeMarc Strapetz via GitGitGadget, Jan 6, 2022
  12. Junio C HamanoJan 6, 2022
  13. 2/4 t7508: fix bogus mtime verificationMarc Strapetz via GitGitGadget, Jan 6, 2022
  14. 3/4 t7508: add tests capturing racy timestamp handlingMarc Strapetz via GitGitGadget, Jan 6, 2022
  15. 4/4 update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Jan 6, 2022
  16. 0/4 update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Jan 7, 2022
  17. 1/4 test-lib: introduce API for verifying file mtimeMarc Strapetz via GitGitGadget, Jan 7, 2022
  18. 2/4 t7508: fix bogus mtime verificationMarc Strapetz via GitGitGadget, Jan 7, 2022
  19. 3/4 t7508: add tests capturing racy timestamp handlingMarc Strapetz via GitGitGadget, Jan 7, 2022
  20. 4/4 update-index: refresh should rewrite index in case of racy timestampsMarc Strapetz via GitGitGadget, Jan 7, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.