summaryrefslogtreecommitdiff
path: root/extra/mariabackup/xtrabackup.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-07-22 09:50:20 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-07-22 10:05:13 +0300
commit82d5994520c239da1b6edf1b24e08138ae0c753d (patch)
tree57960cba641e07952799a86eb5bed816064a128a /extra/mariabackup/xtrabackup.cc
parentbf435a3f4daa90dd6b4b94ed62f05a8e30fecc3d (diff)
downloadmariadb-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.cc39
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;
}