Fix an extent coalesce bug.

When coalescing, we should take both extents off the LRU list; otherwise decay
can grab the existing outer extent through extents_evict.
This commit is contained in:
Qi Wang 2017-11-14 16:09:31 -08:00 committed by Qi Wang
parent fac706836f
commit eb1b08daae
2 changed files with 18 additions and 7 deletions

View File

@ -355,6 +355,11 @@ extent_list_append(extent_list_t *list, extent_t *extent) {
ql_tail_insert(list, extent, ql_link); ql_tail_insert(list, extent, ql_link);
} }
static inline void
extent_list_prepend(extent_list_t *list, extent_t *extent) {
ql_head_insert(list, extent, ql_link);
}
static inline void static inline void
extent_list_replace(extent_list_t *list, extent_t *to_remove, extent_list_replace(extent_list_t *list, extent_t *to_remove,
extent_t *to_insert) { extent_t *to_insert) {

View File

@ -1458,13 +1458,12 @@ extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
bool growing_retained) { bool growing_retained) {
assert(extent_can_coalesce(arena, extents, inner, outer)); assert(extent_can_coalesce(arena, extents, inner, outer));
if (forward && extents->delay_coalesce) { if (extents->delay_coalesce) {
/* /*
* The extent that remains after coalescing must occupy the * Remove outer from the LRU list so that it won't be show up in
* outer extent's position in the LRU. For forward coalescing, * decay through extents_evict.
* swap the inner extent into the LRU.
*/ */
extent_list_replace(&extents->lru, outer, inner); extent_list_remove(&extents->lru, outer);
} }
extent_activate_locked(tsdn, arena, extents, outer, extent_activate_locked(tsdn, arena, extents, outer,
extents->delay_coalesce); extents->delay_coalesce);
@ -1474,9 +1473,16 @@ extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
forward ? inner : outer, forward ? outer : inner, growing_retained); forward ? inner : outer, forward ? outer : inner, growing_retained);
malloc_mutex_lock(tsdn, &extents->mtx); malloc_mutex_lock(tsdn, &extents->mtx);
if (!err && extents->delay_coalesce) {
if (forward) {
extent_list_prepend(&extents->lru, inner);
} else {
extent_list_prepend(&extents->lru, outer);
}
}
if (err) { if (err) {
if (forward && extents->delay_coalesce) { if (extents->delay_coalesce) {
extent_list_replace(&extents->lru, inner, outer); extent_list_prepend(&extents->lru, outer);
} }
extent_deactivate_locked(tsdn, arena, extents, outer, extent_deactivate_locked(tsdn, arena, extents, outer,
extents->delay_coalesce); extents->delay_coalesce);