summaryrefslogtreecommitdiff
path: root/mysys/mf_iocache.c
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2017-02-14 18:31:30 +0200
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2017-02-15 14:09:27 +0200
commitd4746422547f1901831f9c891a3600275daf6534 (patch)
tree81a0b2e136358f2f0f153394196f641c6a03000a /mysys/mf_iocache.c
parent9fe9fb68acd763ad3908c03d82d4de577d6f0c21 (diff)
downloadmariadb-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.c15
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;
}
}