diff options
Diffstat (limited to 'split-index.c')
-rw-r--r-- | split-index.c | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/split-index.c b/split-index.c index 317900db8b..84f067e10d 100644 --- a/split-index.c +++ b/split-index.c @@ -73,16 +73,31 @@ void move_cache_to_base_index(struct index_state *istate) int i; /* - * do not delete old si->base, its index entries may be shared - * with istate->cache[]. Accept a bit of leaking here because - * this code is only used by short-lived update-index. + * If there was a previous base index, then transfer ownership of allocated + * entries to the parent index. */ + if (si->base && + si->base->ce_mem_pool) { + + if (!istate->ce_mem_pool) + mem_pool_init(&istate->ce_mem_pool, 0); + + mem_pool_combine(istate->ce_mem_pool, istate->split_index->base->ce_mem_pool); + } + si->base = xcalloc(1, sizeof(*si->base)); si->base->version = istate->version; /* zero timestamp disables racy test in ce_write_index() */ si->base->timestamp = istate->timestamp; ALLOC_GROW(si->base->cache, istate->cache_nr, si->base->cache_alloc); si->base->cache_nr = istate->cache_nr; + + /* + * The mem_pool needs to move with the allocated entries. + */ + si->base->ce_mem_pool = istate->ce_mem_pool; + istate->ce_mem_pool = NULL; + COPY_ARRAY(si->base->cache, istate->cache, istate->cache_nr); mark_base_index_entries(si->base); for (i = 0; i < si->base->cache_nr; i++) @@ -331,12 +346,31 @@ void remove_split_index(struct index_state *istate) { if (istate->split_index) { /* - * can't discard_split_index(&the_index); because that - * will destroy split_index->base->cache[], which may - * be shared with the_index.cache[]. So yeah we're - * leaking a bit here. + * When removing the split index, we need to move + * ownership of the mem_pool associated with the + * base index to the main index. There may be cache entries + * allocated from the base's memory pool that are shared with + * the_index.cache[]. */ - istate->split_index = NULL; + mem_pool_combine(istate->ce_mem_pool, istate->split_index->base->ce_mem_pool); + + /* + * The split index no longer owns the mem_pool backing + * its cache array. As we are discarding this index, + * mark the index as having no cache entries, so it + * will not attempt to clean up the cache entries or + * validate them. + */ + if (istate->split_index->base) + istate->split_index->base->cache_nr = 0; + + /* + * We can discard the split index because its + * memory pool has been incorporated into the + * memory pool associated with the the_index. + */ + discard_split_index(istate); + istate->cache_changed |= SOMETHING_CHANGED; } } |