From: Junio C Hamano <gitster@pobox.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paolo Bonzini <bonzini@gnu.org>,
Miklos Vajna <vmiklos@frugalware.org>, Jeff King <peff@peff.net>,
git@vger.kernel.org
Subject: [RFH] two and half potential fixlets to the in-core index handling
Date: Sat, 23 Aug 2008 03:41:16 -0700 [thread overview]
Message-ID: <7vbpzkypwz.fsf_-_@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <7v7ia8126z.fsf@gitster.siamese.dyndns.org> (Junio C. Hamano's message of "Sat, 23 Aug 2008 03:00:04 -0700")
While debugging merge-in-C with Miklos, I noticed that relatively recent
codepaths that deal with the in-core index are subtly broken when a single
process calls read_cache() more than once.
A historical invariant in the API is "if you have read the index or
populated it, then the next read_cache() is a no-op and you need to run
discard_cache() beforehand if you want to read a new on-disk index." I
think this was broken by relatively recent unpack-trees rewrite, namely
34110cd (Make 'unpack_trees()' have a separate source and destination
index, 2008-03-06) and also 7a51ed6 (Make on-disk index representation
separate from in-core one, 2008-01-14).
With the current code, unpack_trees() builds its merge into a cleaned
o->result (an index_state structure), and it is copied to o->dst_index,
which often is the_index. But the logic in read_from_index() that
implements the historical invariant checks if istate->alloc is NULL (in
which case the istate is empty -- just after startup, or just after
discard_index()). The "result" index_state does not have alloc because it
is built from scratch and never allocated anything.
This wouldn't work very well.
A hacky solution I have in the attached patch is to waste an xmalloc(1)
and store it there when o->result is created, and also make
read_from_index() pay attention to the cache_nr and the cache_changed
bit. I think it is the safest and minimum fix.
Another independent issue is that istate has name_hash_initialized bit
that records the validity of the name_hash. discard_index() frees the
name_hash, but it never resets the bit to zero. I am not sure what the
ramifications of not doing so, but it certainly feels wrong.
Also, discard_index() did not free the array of pointers istate->cache[];
I think it should.
read-cache.c | 11 ++++-------
unpack-trees.c | 2 ++
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git c/read-cache.c w/read-cache.c
index 2c03ec3..b29f263 100644
--- c/read-cache.c
+++ w/read-cache.c
@@ -1144,7 +1144,7 @@ static inline size_t estimate_cache_size(size_t ondisk_size, unsigned int entrie
return ondisk_size + entries*per_entry;
}
-/* remember to discard_cache() before reading a different cache! */
+/* remember to discard_index() before reading a different cache! */
int read_index_from(struct index_state *istate, const char *path)
{
int fd, i;
@@ -1155,7 +1155,7 @@ int read_index_from(struct index_state *istate, const char *path)
size_t mmap_size;
errno = EBUSY;
- if (istate->alloc)
+ if (istate->alloc || istate->cache_nr || istate->cache_changed)
return istate->cache_nr;
errno = ENOENT;
@@ -1240,15 +1240,12 @@ unmap:
int discard_index(struct index_state *istate)
{
- istate->cache_nr = 0;
- istate->cache_changed = 0;
- istate->timestamp = 0;
free_hash(&istate->name_hash);
cache_tree_free(&(istate->cache_tree));
free(istate->alloc);
- istate->alloc = NULL;
+ free(istate->cache);
- /* no need to throw away allocated active_cache */
+ memset(istate, 0, sizeof(*istate));
return 0;
}
diff --git c/unpack-trees.c w/unpack-trees.c
index cba0aca..016fd46 100644
--- c/unpack-trees.c
+++ w/unpack-trees.c
@@ -378,6 +378,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
memset(&o->result, 0, sizeof(o->result));
if (o->src_index)
o->result.timestamp = o->src_index->timestamp;
+ if (o->dst_index)
+ o->result.alloc = xmalloc(1);
o->merge_size = len;
if (!dfc)
next prev parent reply other threads:[~2008-08-23 10:42 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-22 6:36 [bug] git `next' does not do trivial merges Paolo Bonzini
2008-08-22 19:31 ` Jeff King
2008-08-23 6:08 ` Miklos Vajna
2008-08-23 8:14 ` [PATCH] Fix in-index merge Miklos Vajna
2008-08-23 8:17 ` [PATCH] builtin-merge: fail properly when we are in the middle of a conflicted merge Miklos Vajna
2008-08-23 9:01 ` Junio C Hamano
2008-08-23 10:57 ` Miklos Vajna
2008-08-23 19:55 ` Junio C Hamano
2008-08-23 19:56 ` [PATCH 1/2] merge: fix numerus bugs around "trivial merge" area Junio C Hamano
2008-08-24 1:58 ` Junio C Hamano
2008-08-28 13:43 ` [PATCH] builtin-merge: avoid run_command_v_opt() for recursive and subtree Miklos Vajna
2008-08-23 19:57 ` [PATCH 2/2] unpack_trees(): protect the handcrafted in-core index from read_cache() Junio C Hamano
2008-08-23 9:50 ` [PATCH] builtin-merge: fail properly when we are in the middle of a conflicted merge Junio C Hamano
2008-08-23 8:50 ` [PATCH] Fix in-index merge Junio C Hamano
2008-08-23 10:41 ` Miklos Vajna
2008-08-23 9:19 ` Paolo Bonzini
2008-08-23 9:55 ` Junio C Hamano
2008-08-23 10:00 ` Junio C Hamano
2008-08-23 10:41 ` Junio C Hamano [this message]
2008-08-23 18:13 ` [RFH] two and half potential fixlets to the in-core index handling Linus Torvalds
2008-08-23 19:14 ` Junio C Hamano
2008-08-23 19:21 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7vbpzkypwz.fsf_-_@gitster.siamese.dyndns.org \
--to=gitster@pobox.com \
--cc=bonzini@gnu.org \
--cc=git@vger.kernel.org \
--cc=peff@peff.net \
--cc=torvalds@linux-foundation.org \
--cc=vmiklos@frugalware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.