Re: [PATCH v1] Fix bugs preventing adding updated cache entries to the name hash

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 3/15/2018 1:58 PM, Junio C Hamano wrote:
Ben Peart <benpeart@xxxxxxxxxxxxx> writes:

Update replace_index_entry() to clear the CE_HASHED flag from the new cache
entry so that it can add it to the name hash in set_index_entry()

OK.

diff --git a/read-cache.c b/read-cache.c
index 977921d90c..bdfa552861 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -62,6 +62,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
  	replace_index_entry_in_base(istate, old, ce);
  	remove_name_hash(istate, old);
  	free(old);
+	ce->ce_flags &= ~CE_HASHED;
  	set_index_entry(istate, nr, ce);
  	ce->ce_flags |= CE_UPDATE_IN_BASE;
  	mark_fsmonitor_invalid(istate, ce);

As we are removing "old" that is not "ce", an earlier call to
remove_name_hash() that clears the CE_HASHED bit from the cache
entry does not help us at all.  We need to clear the bit from "ce"
ourselves before calling set_index_entry() on it, otherwise the call
would become a no-op wrt the name hash.  Makes sense.


Correct. As you note below, this one line is sufficient to fix the actual bug.

Makes me wonder why "ce" which is a replacement for what is in the
index already has the hashed bit, though.  Is that the failure to
use copy_cache_entry() in the caller the other part of this patch
fixes?  To me it looks like copy_cache_entry() is designed for
copying an entry's data to another one that has a different name,
but in the refresh codepath, we _know_ we are replacing an old entry
with an entry with the same name, so it somehow feels a bit strange
to use copy_cache_entry(), instead of doing memcpy() (and possibly
dropping the HASHED bit from the new copy--but wouldn't that become
unnecessary with the fix to replace_index_entry() we saw above?)


This 2nd part of the patch was more for code cleanliness. When I was investigating why the hashed bit was set, it was caused by this memcpy(). When I examined the rest of the code base, I only found 1 other instance (in dup_entry()) that did a straight memcpy(), the rest used the copy_cache_entry() macro. I updated this code to match that pattern as it would have prevented the bug as well though as you correctly point out, it is not necessary with the other fix.

Is this fix something we can demonstrate in a new test, by the way?


Unfortunately I was unable to find a way to reliably demonstrate this bug and fix with a new test. I only ran across it while working on another patch series that ends up triggering it more reliably.

The symptom was that occasionally in very specific circumstances a git status call would incorrectly show some directories as having untracked files when there were actually no untracked files in that directory. A subsequent call to status would correctly show no untracked files as would git status -uall.

I do have a test for this fix as part of the other patch series but thought I'd submit this bug fix separately as it may be a while before the other patch series is ready.

Thanks.




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux