[Commits] 0918ae42a83: MDEV-14014 Multi-Slave Replication Fail: bogus data in log event
revision-id: 0918ae42a8394b6faf28f67b70550894851be3bb (mariadb-10.1.33-36-g0918ae42a83) parent(s): 26be5072429082e634b8fc102609370975443439 author: Andrei Elkin committer: Andrei Elkin timestamp: 2018-06-13 16:27:00 +0300 message: MDEV-14014 Multi-Slave Replication Fail: bogus data in log event MDEV-7257 made a dump thread to read from binlog concurrently with writers as long as the read bytes are below a water-mark (MYSQL_BIN_LOG::binlog_end_pos). However it appeared to be possible a dump thread reader reach out for bytes past the water mark through a feature of IO_CACHE that fills in the internal buffer and while doing so it could read what the reader is not supposed to see (the bytes above MYSQL_BIN_LOG::binlog_end_pos). The issue is fixed with constraining the IO_CACHE buffer fill to respect the watermark. An added test simulates potentially unconstrained buffer fill and an assert guards this is not the case anymore. --- sql/sql_repl.cc | 1 + unittest/sql/mf_iocache-t.cc | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 569c3d2c4ef..db608de5147 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2546,6 +2546,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo, linfo->pos= my_b_tell(log); info->last_pos= my_b_tell(log); + log->end_of_file= end_pos; while (linfo->pos < end_pos) { if (should_stop(info)) diff --git a/unittest/sql/mf_iocache-t.cc b/unittest/sql/mf_iocache-t.cc index 1b04f8eb0d3..edc4c3ce789 100644 --- a/unittest/sql/mf_iocache-t.cc +++ b/unittest/sql/mf_iocache-t.cc @@ -253,6 +253,39 @@ void mdev10259() } +void mdev14014() +{ + int res; + uchar buf_o[200]; + uchar buf_i[200]; + memset(buf_i, 0, sizeof( buf_i)); + memset(buf_o, FILL, sizeof(buf_o)); + + diag("MDEV-14014 Dump thread reads past last 'officially' written byte"); + + init_io_cache_encryption(); + + res= open_cached_file(&info, 0, 0, CACHE_SIZE, 0); + ok(res == 0, "open_cached_file" INFO_TAIL); + + res= my_b_write(&info, buf_o, sizeof(buf_o)); + ok(res == 0, "buffer is written" INFO_TAIL); + + res= my_b_flush_io_cache(&info, 1); + ok(res == 0, "flush" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit READ_CACHE" INFO_TAIL); + + info.end_of_file= 100; + res= my_b_read(&info, buf_i, sizeof(buf_i)); + ok(res == 1 && buf_i[100] == 0 && buf_i[200-1] == 0, + "short read leaves buf_i[100..200-1] == 0"); + + close_cached_file(&info); +} + + int main(int argc __attribute__((unused)),char *argv[]) { MY_INIT(argv[0]); @@ -272,6 +305,8 @@ int main(int argc __attribute__((unused)),char *argv[]) mdev10259(); encrypt_tmp_files= 0; + mdev14014(); + my_end(0); return exit_status(); }
participants (1)
-
andrei.elkin@pp.inet.fi