diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2017-02-14 18:31:30 +0200 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2017-02-15 14:09:27 +0200 |
commit | d4746422547f1901831f9c891a3600275daf6534 (patch) | |
tree | 81a0b2e136358f2f0f153394196f641c6a03000a /mysys/mf_iocache.c | |
parent | 9fe9fb68acd763ad3908c03d82d4de577d6f0c21 (diff) | |
download | mariadb-git-d4746422547f1901831f9c891a3600275daf6534.tar.gz |
MDEV-10092: Server crashes in in ha_heap::rnd_pos / Table_read_cursor::get_next
The bug was caused by several issues.
2 problems in seek_io_cache. Due to wrong offsets used, we would end up
seeking way too much (first change), or over the intended seek point
(second change). Fixing it requires correctly detecting available data
in buffer (first change), and not using "IO_SIZE alligned" reads. The
second is needed because _my_b_cache_read adjusts the pos_in_file itself
based on read_pos and read_end. Pretending buffer is empty when we want
to force a read will aleviate this problem.
Secondly, the big-table cursors didn't repect the interface definitions
of always returning the rownumber that Table_read_cursor::fetch() would activate.
At the same time, next(), prev() and move_to() should not perform any
row activation.
Diffstat (limited to 'mysys/mf_iocache.c')
-rw-r--r-- | mysys/mf_iocache.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index bfdda25cafa..72385daef42 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -397,8 +397,9 @@ void end_slave_io_cache(IO_CACHE *cache) void seek_io_cache(IO_CACHE *cache, my_off_t needed_offset) { my_off_t cached_data_start= cache->pos_in_file; - my_off_t cached_data_end= cache->pos_in_file + (cache->read_pos - + my_off_t cached_data_end= cache->pos_in_file + (cache->read_end - cache->buffer); + if (needed_offset >= cached_data_start && needed_offset < cached_data_end) { @@ -416,11 +417,17 @@ void seek_io_cache(IO_CACHE *cache, my_off_t needed_offset) The offset we're seeking to is not in the buffer. - Set the buffer to be exhausted. - Make the next read to a mysql_file_seek() call to the required - offset (but still use aligned reads). + offset. + TODO(cvicentiu, spetrunia) properly implement aligned seeks for + efficiency. */ - cache->read_pos= cache->read_end; cache->seek_not_done= 1; - cache->pos_in_file= (needed_offset / IO_SIZE) * IO_SIZE; + cache->pos_in_file= needed_offset; + /* When reading it must appear as if we've started from the offset + that we've seeked here. We must let _my_b_cache_read assume that + by implying "no reading starting from pos_in_file" has happened. */ + cache->read_pos= cache->buffer; + cache->read_end= cache->buffer; } } |