Commit 7f9dc0d8 authored by Eugene Kosov's avatar Eugene Kosov

split log_t::buf into two buffers

Maybe this patch will help catch problems like buffer overflow.

log_t::first_in_use: removed

log_t::buf: this is where mtr_t are supposed to append data
log_t::flush_buf: this is from server writes to a file

Those two buffers are std::swap()ped when some thread is gonna write
to a file
parent 1fbdcada
...@@ -1246,11 +1246,12 @@ buf_madvise_do_dump() ...@@ -1246,11 +1246,12 @@ buf_madvise_do_dump()
/* mirrors allocation in log_t::create() */ /* mirrors allocation in log_t::create() */
if (log_sys.buf) { if (log_sys.buf) {
ret+= madvise(log_sys.first_in_use ret += madvise(log_sys.buf,
? log_sys.buf srv_log_buffer_size,
: log_sys.buf - srv_log_buffer_size, MADV_DODUMP);
srv_log_buffer_size * 2, ret += madvise(log_sys.flush_buf,
MADV_DODUMP); srv_log_buffer_size,
MADV_DODUMP);
} }
/* mirrors recv_sys_init() */ /* mirrors recv_sys_init() */
if (recv_sys->buf) if (recv_sys->buf)
......
...@@ -524,19 +524,11 @@ struct log_t{ ...@@ -524,19 +524,11 @@ struct log_t{
mtr_commit and still ensure that mtr_commit and still ensure that
insertions in the flush_list happen insertions in the flush_list happen
in the LSN order. */ in the LSN order. */
byte* buf; /*!< Memory of double the /** log_buffer, append data here */
srv_log_buffer_size is byte* buf;
allocated here. This pointer will change /** log_buffer, writing data to file from this buffer.
however to either the first half or the Before flushing write_buf is swapped with flush_buf */
second half in turns, so that log byte* flush_buf;
write/flush to disk don't block
concurrent mtrs which will write
log to this buffer. Care to switch back
to the first half before freeing/resizing
must be undertaken. */
bool first_in_use; /*!< true if buf points to the first
half of the buffer, false
if the second half */
ulong max_buf_free; /*!< recommended maximum value of ulong max_buf_free; /*!< recommended maximum value of
buf_free for the buffer in use, after buf_free for the buffer in use, after
which the buffer is flushed */ which the buffer is flushed */
......
...@@ -162,16 +162,19 @@ log_buf_pool_get_oldest_modification(void) ...@@ -162,16 +162,19 @@ log_buf_pool_get_oldest_modification(void)
void log_buffer_extend(ulong len) void log_buffer_extend(ulong len)
{ {
const ulong new_buf_size = ut_calc_align(len, srv_page_size); const ulong new_buf_size = ut_calc_align(len, srv_page_size);
byte* new_buf = static_cast<byte*>( byte* new_buf = static_cast<byte*>(ut_malloc_dontdump(new_buf_size));
ut_malloc_dontdump(new_buf_size * 2)); TRASH_ALLOC(new_buf, new_buf_size);
TRASH_ALLOC(new_buf, new_buf_size * 2); byte* new_flush_buf =
static_cast<byte*>(ut_malloc_dontdump(new_buf_size));
TRASH_ALLOC(new_flush_buf, new_buf_size);
log_mutex_enter(); log_mutex_enter();
if (len <= srv_log_buffer_size) { if (len <= srv_log_buffer_size) {
/* Already extended enough by the others */ /* Already extended enough by the others */
log_mutex_exit(); log_mutex_exit();
ut_free_dodump(new_buf, new_buf_size * 2); ut_free_dodump(new_buf, new_buf_size);
ut_free_dodump(new_flush_buf, new_buf_size);
return; return;
} }
...@@ -179,14 +182,14 @@ void log_buffer_extend(ulong len) ...@@ -179,14 +182,14 @@ void log_buffer_extend(ulong len)
" exceeds innodb_log_buffer_size=" " exceeds innodb_log_buffer_size="
<< srv_log_buffer_size << " / 2). Trying to extend it."; << srv_log_buffer_size << " / 2). Trying to extend it.";
const byte* old_buf_begin = log_sys.buf; byte* old_buf = log_sys.buf;
byte* old_flush_buf = log_sys.flush_buf;
const ulong old_buf_size = srv_log_buffer_size; const ulong old_buf_size = srv_log_buffer_size;
byte* old_buf = log_sys.first_in_use
? log_sys.buf : log_sys.buf - old_buf_size;
srv_log_buffer_size = new_buf_size; srv_log_buffer_size = new_buf_size;
log_sys.buf = new_buf; log_sys.buf = new_buf;
log_sys.first_in_use = true; log_sys.flush_buf = new_flush_buf;
memcpy(log_sys.buf, old_buf_begin, log_sys.buf_free); memcpy(new_buf, old_buf, log_sys.buf_free);
log_sys.max_buf_free = new_buf_size / LOG_BUF_FLUSH_RATIO log_sys.max_buf_free = new_buf_size / LOG_BUF_FLUSH_RATIO
- LOG_BUF_FLUSH_MARGIN; - LOG_BUF_FLUSH_MARGIN;
...@@ -194,6 +197,7 @@ void log_buffer_extend(ulong len) ...@@ -194,6 +197,7 @@ void log_buffer_extend(ulong len)
log_mutex_exit(); log_mutex_exit();
ut_free_dodump(old_buf, old_buf_size); ut_free_dodump(old_buf, old_buf_size);
ut_free_dodump(old_flush_buf, old_buf_size);
ib::info() << "innodb_log_buffer_size was extended to " ib::info() << "innodb_log_buffer_size was extended to "
<< new_buf_size << "."; << new_buf_size << ".";
...@@ -547,10 +551,10 @@ void log_t::create() ...@@ -547,10 +551,10 @@ void log_t::create()
ut_ad(srv_log_buffer_size >= 16 * OS_FILE_LOG_BLOCK_SIZE); ut_ad(srv_log_buffer_size >= 16 * OS_FILE_LOG_BLOCK_SIZE);
ut_ad(srv_log_buffer_size >= 4U << srv_page_size_shift); ut_ad(srv_log_buffer_size >= 4U << srv_page_size_shift);
buf= static_cast<byte*>(ut_malloc_dontdump(srv_log_buffer_size * 2)); buf= static_cast<byte*>(ut_malloc_dontdump(srv_log_buffer_size));
TRASH_ALLOC(buf, srv_log_buffer_size * 2); TRASH_ALLOC(buf, srv_log_buffer_size);
flush_buf= static_cast<byte*>(ut_malloc_dontdump(srv_log_buffer_size));
first_in_use= true; TRASH_ALLOC(flush_buf, srv_log_buffer_size);
max_buf_free= srv_log_buffer_size / LOG_BUF_FLUSH_RATIO - max_buf_free= srv_log_buffer_size / LOG_BUF_FLUSH_RATIO -
LOG_BUF_FLUSH_MARGIN; LOG_BUF_FLUSH_MARGIN;
...@@ -824,8 +828,8 @@ log_write_flush_to_disk_low() ...@@ -824,8 +828,8 @@ log_write_flush_to_disk_low()
os_event_set(log_sys.flush_event); os_event_set(log_sys.flush_event);
} }
/** Switch the log buffer in use, and copy the content of last block /** Swap log buffers, and copy the content of last block
from old log buffer to the head of the to be used one. Thus, buf_free and from old buf to the head of the new buf. Thus, buf_free and
buf_next_to_write would be changed accordingly */ buf_next_to_write would be changed accordingly */
static inline static inline
void void
...@@ -834,27 +838,16 @@ log_buffer_switch() ...@@ -834,27 +838,16 @@ log_buffer_switch()
ut_ad(log_mutex_own()); ut_ad(log_mutex_own());
ut_ad(log_write_mutex_own()); ut_ad(log_write_mutex_own());
const byte* old_buf = log_sys.buf;
ulong area_end = ut_calc_align( ulong area_end = ut_calc_align(
log_sys.buf_free, ulong(OS_FILE_LOG_BLOCK_SIZE)); log_sys.buf_free, ulong(OS_FILE_LOG_BLOCK_SIZE));
if (log_sys.first_in_use) {
log_sys.first_in_use = false;
ut_ad(log_sys.buf == ut_align(log_sys.buf,
OS_FILE_LOG_BLOCK_SIZE));
log_sys.buf += srv_log_buffer_size;
} else {
log_sys.first_in_use = true;
log_sys.buf -= srv_log_buffer_size;
ut_ad(log_sys.buf == ut_align(log_sys.buf,
OS_FILE_LOG_BLOCK_SIZE));
}
/* Copy the last block to new buf */ /* Copy the last block to new buf */
ut_memcpy(log_sys.buf, ut_memcpy(log_sys.flush_buf,
old_buf + area_end - OS_FILE_LOG_BLOCK_SIZE, log_sys.buf + area_end - OS_FILE_LOG_BLOCK_SIZE,
OS_FILE_LOG_BLOCK_SIZE); OS_FILE_LOG_BLOCK_SIZE);
std::swap(log_sys.buf, log_sys.flush_buf);
log_sys.buf_free %= OS_FILE_LOG_BLOCK_SIZE; log_sys.buf_free %= OS_FILE_LOG_BLOCK_SIZE;
log_sys.buf_next_to_write = log_sys.buf_free; log_sys.buf_next_to_write = log_sys.buf_free;
} }
...@@ -1942,10 +1935,10 @@ void log_t::close() ...@@ -1942,10 +1935,10 @@ void log_t::close()
m_initialised = false; m_initialised = false;
log.close(); log.close();
if (!first_in_use) ut_free_dodump(buf, srv_log_buffer_size);
buf -= srv_log_buffer_size;
ut_free_dodump(buf, srv_log_buffer_size * 2);
buf = NULL; buf = NULL;
ut_free_dodump(flush_buf, srv_log_buffer_size);
flush_buf = NULL;
os_event_destroy(flush_event); os_event_destroy(flush_event);
rw_lock_free(&checkpoint_lock); rw_lock_free(&checkpoint_lock);
......
...@@ -502,6 +502,7 @@ create_log_files( ...@@ -502,6 +502,7 @@ create_log_files(
memset(log_sys.buf, 0, srv_log_buffer_size); memset(log_sys.buf, 0, srv_log_buffer_size);
log_block_init(log_sys.buf, log_sys.lsn); log_block_init(log_sys.buf, log_sys.lsn);
log_block_set_first_rec_group(log_sys.buf, LOG_BLOCK_HDR_SIZE); log_block_set_first_rec_group(log_sys.buf, LOG_BLOCK_HDR_SIZE);
memset(log_sys.flush_buf, 0, srv_log_buffer_size);
log_sys.buf_free = LOG_BLOCK_HDR_SIZE; log_sys.buf_free = LOG_BLOCK_HDR_SIZE;
log_sys.lsn += LOG_BLOCK_HDR_SIZE; log_sys.lsn += LOG_BLOCK_HDR_SIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment