From 3a73e5dcaa8c5e6cf647e94eb6dab98964c0193c Mon Sep 17 00:00:00 2001 From: Vladimir Davydov <vdavydov.dev@gmail.com> Date: Mon, 10 Jul 2017 13:51:21 +0300 Subject: [PATCH] vinyl: add missing mem_list_version increment vy_task_dump_new() deletes empty in-memory trees right away, but doesn't increment vy_index->mem_list_version, which may result in a read iterator crash accessing a deleted vy_mem. --- src/box/vinyl.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/box/vinyl.c b/src/box/vinyl.c index a430adee78..8234da545c 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -1389,6 +1389,20 @@ vy_index_rotate_mem(struct vy_index *index) return 0; } +/** + * Remove an in-memory tree from the sealed list of a vinyl index, + * unaccount and delete it. + */ +static void +vy_index_delete_mem(struct vy_index *index, struct vy_mem *mem) +{ + assert(!rlist_empty(&mem->in_sealed)); + rlist_del_entry(mem, in_sealed); + vy_stmt_counter_sub(&index->stat.memory.count, &mem->count); + vy_mem_delete(mem); + index->mem_list_version++; +} + /** * Split a range if it has grown too big, return true if the range * was split. Splitting is done by making slices of the runs used @@ -2467,12 +2481,9 @@ vy_task_dump_complete(struct vy_task *task) rlist_foreach_entry_safe(mem, &index->sealed, in_sealed, next_mem) { if (mem->generation > scheduler->dump_generation) continue; - rlist_del_entry(mem, in_sealed); - vy_stmt_counter_sub(&index->stat.memory.count, &mem->count); vy_stmt_counter_add(&index->stat.disk.dump.in, &mem->count); - vy_mem_delete(mem); + vy_index_delete_mem(index, mem); } - index->mem_list_version++; index->dump_lsn = dump_lsn; index->stat.disk.dump.count++; @@ -2584,10 +2595,7 @@ vy_task_dump_new(struct vy_index *index, struct vy_task **p_task) * The tree is empty so we can delete it * right away, without involving a worker. */ - vy_stmt_counter_sub(&index->stat.memory.count, - &mem->count); - rlist_del_entry(mem, in_sealed); - vy_mem_delete(mem); + vy_index_delete_mem(index, mem); continue; } dump_lsn = MAX(dump_lsn, mem->max_lsn); -- GitLab