diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-07-22 09:50:20 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-07-22 10:05:13 +0300 |
commit | 82d5994520c239da1b6edf1b24e08138ae0c753d (patch) | |
tree | 57960cba641e07952799a86eb5bed816064a128a /extra/mariabackup/xtrabackup.cc | |
parent | bf435a3f4daa90dd6b4b94ed62f05a8e30fecc3d (diff) | |
download | mariadb-git-82d5994520c239da1b6edf1b24e08138ae0c753d.tar.gz |
MDEV-26110: Do not rely on alignment on static allocation
It is implementation-defined whether alignment requirements
that are larger than std::max_align_t (typically 8 or 16 bytes)
will be honored by the compiler and linker.
It turns out that on IBM AIX, both alignas() and MY_ALIGNED()
only guarantees alignment up to 16 bytes.
For some data structures, specifying alignment to the CPU
cache line size (typically 64 or 128 bytes) is a mere performance
optimization, and we do not really care whether the requested
alignment is guaranteed.
But, for the correct operation of direct I/O, we do require that
the buffers be aligned at a block size boundary.
field_ref_zero: Define as a pointer, not an array.
For innochecksum, we can make this point to unaligned memory;
for anything else, we will allocate an aligned buffer from the heap.
This buffer will be used for overwriting freed data pages when
innodb_immediate_scrub_data_uncompressed=ON. And exactly that code
hit an assertion failure on AIX, in the test innodb.innodb_scrub.
log_sys.checkpoint_buf: Define as a pointer to aligned memory
that is allocated from heap.
log_t::file::write_header_durable(): Reuse log_sys.checkpoint_buf
instead of trying to allocate an aligned buffer from the stack.
Diffstat (limited to 'extra/mariabackup/xtrabackup.cc')
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 7ec6fbb8f59..bf4a80832dc 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4501,6 +4501,14 @@ fail: goto fail; } + + if (auto b = aligned_malloc(UNIV_PAGE_SIZE_MAX, 4096)) { + field_ref_zero = static_cast<byte*>( + memset_aligned<4096>(b, 0, UNIV_PAGE_SIZE_MAX)); + } else { + goto fail; + } + { /* definition from recv_recovery_from_checkpoint_start() */ ulint max_cp_field; @@ -4515,14 +4523,17 @@ reread_log_header: if (err != DB_SUCCESS) { msg("Error: cannot read redo log header"); +unlock_and_fail: mysql_mutex_unlock(&log_sys.mutex); +free_and_fail: + aligned_free(const_cast<byte*>(field_ref_zero)); + field_ref_zero = nullptr; goto fail; } if (log_sys.log.format == 0) { msg("Error: cannot process redo log before MariaDB 10.2.2"); - mysql_mutex_unlock(&log_sys.mutex); - goto fail; + goto unlock_and_fail; } byte* buf = log_sys.checkpoint_buf; @@ -4543,7 +4554,7 @@ reread_log_header: xtrabackup_init_datasinks(); if (!select_history()) { - goto fail; + goto free_and_fail; } /* open the log file */ @@ -4552,12 +4563,13 @@ reread_log_header: if (dst_log_file == NULL) { msg("Error: failed to open the target stream for '%s'.", LOG_FILE_NAME); - goto fail; + goto free_and_fail; } /* label it */ - byte MY_ALIGNED(OS_FILE_LOG_BLOCK_SIZE) log_hdr_buf[LOG_FILE_HDR_SIZE]; - memset(log_hdr_buf, 0, sizeof log_hdr_buf); + byte* log_hdr_buf = static_cast<byte*>( + aligned_malloc(LOG_FILE_HDR_SIZE, OS_FILE_LOG_BLOCK_SIZE)); + memset(log_hdr_buf, 0, LOG_FILE_HDR_SIZE); byte *log_hdr_field = log_hdr_buf; mach_write_to_4(LOG_HEADER_FORMAT + log_hdr_field, log_sys.log.format); @@ -4586,11 +4598,13 @@ reread_log_header: log_block_calc_checksum_crc32(log_hdr_field)); /* Write log header*/ - if (ds_write(dst_log_file, log_hdr_buf, sizeof(log_hdr_buf))) { + if (ds_write(dst_log_file, log_hdr_buf, LOG_FILE_HDR_SIZE)) { msg("error: write to logfile failed"); - goto fail; + aligned_free(log_hdr_buf); + goto free_and_fail; } + aligned_free(log_hdr_buf); log_copying_running = true; /* start io throttle */ if(xtrabackup_throttle) { @@ -4608,7 +4622,7 @@ reread_log_header: " error %s.", ut_strerr(err)); fail_before_log_copying_thread_start: log_copying_running = false; - goto fail; + goto free_and_fail; } /* copy log file by current position */ @@ -4625,7 +4639,7 @@ fail_before_log_copying_thread_start: /* FLUSH CHANGED_PAGE_BITMAPS call */ if (!flush_changed_page_bitmaps()) { - goto fail; + goto free_and_fail; } ut_a(xtrabackup_parallel > 0); @@ -4647,7 +4661,7 @@ fail_before_log_copying_thread_start: datafiles_iter_t *it = datafiles_iter_new(); if (it == NULL) { msg("mariabackup: Error: datafiles_iter_new() failed."); - goto fail; + goto free_and_fail; } /* Create data copying threads */ @@ -4702,6 +4716,9 @@ fail_before_log_copying_thread_start: if (opt_log_innodb_page_corruption) ok = corrupted_pages.print_to_file(MB_CORRUPTED_PAGES_FILE); + aligned_free(const_cast<byte*>(field_ref_zero)); + field_ref_zero = nullptr; + if (!ok) { goto fail; } |