diff options
author | Eugene Kosov <claprix@yandex.ru> | 2020-01-21 22:22:48 +0800 |
---|---|---|
committer | Eugene Kosov <claprix@yandex.ru> | 2020-01-23 00:12:43 +0800 |
commit | 700e010309ea9d0f7c32d0973ec88c3140c67956 (patch) | |
tree | 28d297e65ea60ffee9cb3c2913040c6c2de2ca04 | |
parent | cdd54c852a8491b7e0b949058e0bf7040015f31f (diff) | |
download | mariadb-git-700e010309ea9d0f7c32d0973ec88c3140c67956.tar.gz |
fix aligned memcpy()-like functions usage
I found that memcpy_aligned was used incorrectly at redo log and decided to put
assertions in aligned functions. And found even more incorrect cases.
Given the amount discovered of bugs, I left assertions to prevent future bugs.
my_assume_aligned(): instead of MY_ASSUME_ALIGNED macro
-rw-r--r-- | include/m_string.h | 31 | ||||
-rw-r--r-- | storage/innobase/btr/btr0btr.cc | 10 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0file.cc | 2 | ||||
-rw-r--r-- | storage/innobase/include/log0log.ic | 3 | ||||
-rw-r--r-- | storage/innobase/include/page0page.h | 3 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 3 | ||||
-rw-r--r-- | storage/innobase/os/os0file.cc | 2 | ||||
-rw-r--r-- | storage/innobase/page/page0page.cc | 5 | ||||
-rw-r--r-- | storage/innobase/page/page0zip.cc | 5 | ||||
-rw-r--r-- | storage/innobase/row/row0import.cc | 4 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 2 |
11 files changed, 38 insertions, 32 deletions
diff --git a/include/m_string.h b/include/m_string.h index 068460f878c..9e786908dc6 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -197,37 +197,50 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); } # ifdef _MSC_VER -# define MY_ASSUME_ALIGNED(x,n) x +template <size_t Alignment, class T> static inline T my_assume_aligned(T ptr) +{ + DBUG_ASSERT(reinterpret_cast<size_t>(ptr) % Alignment == 0); + __assume(reinterpret_cast<size_t>(ptr) % Alignment == 0); + return ptr; +} # else -# define MY_ASSUME_ALIGNED(x,n) __builtin_assume_aligned(x,n) +template <size_t Alignment, class T> static inline T my_assume_aligned(T ptr) +{ + DBUG_ASSERT(reinterpret_cast<size_t>(ptr) % Alignment == 0); + return static_cast<T>(__builtin_assume_aligned(ptr, Alignment)); +} # endif template <size_t Alignment> inline void *memcpy_aligned(void *dest, const void *src, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); - return memcpy(MY_ASSUME_ALIGNED(dest, Alignment), - MY_ASSUME_ALIGNED(src, Alignment), n); + + return memcpy(my_assume_aligned<Alignment>(dest), + my_assume_aligned<Alignment>(src), n); } template <size_t Alignment> inline void *memmove_aligned(void *dest, const void *src, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); - return memmove(MY_ASSUME_ALIGNED(dest, Alignment), - MY_ASSUME_ALIGNED(src, Alignment), n); + + return memmove(my_assume_aligned<Alignment>(dest), + my_assume_aligned<Alignment>(src), n); } template <size_t Alignment> inline int memcmp_aligned(const void *s1, const void *s2, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); - return memcmp(MY_ASSUME_ALIGNED(s1, Alignment), - MY_ASSUME_ALIGNED(s2, Alignment), n); + + return memcmp(my_assume_aligned<Alignment>(s1), + my_assume_aligned<Alignment>(s2), n); } template <size_t Alignment> inline void *memset_aligned(void *s, int c, size_t n) { static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); - return memset(MY_ASSUME_ALIGNED(s, Alignment), c, n); + + return memset(my_assume_aligned<Alignment>(s), c, n); } #endif diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index ec8bdf9c60d..753ed9b077c 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1967,9 +1967,8 @@ btr_root_raise_and_insert( the field only matters on leaf pages, and the root no longer is a leaf page. (Older versions of InnoDB did set PAGE_MAX_TRX_ID on all secondary index pages.) */ - byte* p = static_cast<byte*>( - MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID - + root->frame, 8)); + byte* p = my_assume_aligned<8>( + PAGE_HEADER + PAGE_MAX_TRX_ID + root->frame); if (UNIV_LIKELY_NULL(root_page_zip)) { memset_aligned<8>(p, 0, 8); page_zip_write_header(root_page_zip, p, 8, mtr); @@ -1980,9 +1979,8 @@ btr_root_raise_and_insert( /* PAGE_ROOT_AUTO_INC is only present in the clustered index root page; on other clustered index pages, we want to reserve the field PAGE_MAX_TRX_ID for future use. */ - byte* p = static_cast<byte*>( - MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID - + new_block->frame, 8)); + byte* p = my_assume_aligned<8>( + PAGE_HEADER + PAGE_MAX_TRX_ID + new_block->frame); if (UNIV_LIKELY_NULL(new_page_zip)) { memset_aligned<8>(p, 0, 8); page_zip_write_header(new_page_zip, p, 8, mtr); diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 3e14ed62270..6f133b8db78 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -338,7 +338,7 @@ Datafile::read_first_page(bool read_only_mode) } if (m_order == 0) { - if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + m_first_page, + if (memcmp_aligned<2>(FIL_PAGE_SPACE_ID + m_first_page, FSP_HEADER_OFFSET + FSP_SPACE_ID + m_first_page, 4)) { ib::error() diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic index 447ed647b9f..3f9039cd2b6 100644 --- a/storage/innobase/include/log0log.ic +++ b/storage/innobase/include/log0log.ic @@ -298,8 +298,7 @@ log_reserve_and_write_fast( *start_lsn = log_sys.lsn; - memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf + log_sys.buf_free, - str, len); + memcpy(log_sys.buf + log_sys.buf_free, str, len); log_block_set_data_len( reinterpret_cast<byte*>(ut_align_down( diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index b0a9993ae3f..a4a7ac4b2b2 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -398,8 +398,7 @@ page_rec_is_infimum(const rec_t* rec); inline trx_id_t page_get_max_trx_id(const page_t *page) { static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); - const byte *p= static_cast<const byte*> - (MY_ASSUME_ALIGNED(page + PAGE_HEADER + PAGE_MAX_TRX_ID, 8)); + const auto *p= my_assume_aligned<8>(page + PAGE_HEADER + PAGE_MAX_TRX_ID); return mach_read_from_8(p); } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 42af21f3d9f..752dc488ec9 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -355,8 +355,7 @@ part_loop: - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; } - memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf + log_sys.buf_free, - str, len); + memcpy(log_sys.buf + log_sys.buf_free, str, len); str_len -= len; str = str + len; diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 8010a9b9d0a..fde32c822e1 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4518,7 +4518,7 @@ corrupted: return false; } - const ulint space_id = memcmp_aligned<4>( + const ulint space_id = memcmp_aligned<2>( FIL_PAGE_SPACE_ID + page, FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4) ? ULINT_UNDEFINED diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 5800baf56c9..869b51608bf 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -199,9 +199,8 @@ page_set_max_trx_id( { ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); - byte *max_trx_id= static_cast<byte*>(MY_ASSUME_ALIGNED(PAGE_MAX_TRX_ID - + PAGE_HEADER - + block->frame, 8)); + byte *max_trx_id= my_assume_aligned<8>(PAGE_MAX_TRX_ID + + PAGE_HEADER + block->frame); if (UNIV_LIKELY_NULL(page_zip)) { diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 1e51621e0da..fc6d4a5b9ec 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -84,7 +84,7 @@ static const byte infimum_data[] = { 0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */ }; /** Extra bytes and data bytes of a supremum record */ -static const byte supremum_extra_data[] = { +static const byte supremum_extra_data alignas(4) [] = { /* 0x0?, */ /* info_bits=0, n_owned=1..8 */ 0x00, 0x0b, /* heap_no=1, status=3 */ 0x00, 0x00, /* next=0 */ @@ -4573,8 +4573,7 @@ page_zip_dir_add_slot( /* Move the uncompressed area backwards to make space for one directory slot. */ - memmove_aligned<2>(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, - ulint(dir - stored)); + memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, ulint(dir - stored)); } /***********************************************************//** diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index a31c7288121..a7ab1d12901 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2015,7 +2015,7 @@ clear_page_max_trx_id: inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW { byte *frame= get_frame(block); - if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + frame, + if (memcmp_aligned<2>(FIL_PAGE_SPACE_ID + frame, FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, 4)) ib::warn() << "Space id check in the header failed: ignored"; else if (!mach_read_from_4(FIL_PAGE_SPACE_ID + frame)) @@ -2025,7 +2025,7 @@ inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW /* Write space_id to the tablespace header, page 0. */ mach_write_to_4(FIL_PAGE_SPACE_ID + frame, get_space_id()); - memcpy_aligned<4>(FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, + memcpy_aligned<2>(FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, FIL_PAGE_SPACE_ID + frame, 4); /* Write back the adjusted flags. */ mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame, m_space_flags); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index bdf62df04ff..caa864b6e0b 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -619,7 +619,7 @@ err_exit: uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page); if (id == 0 || id >= SRV_SPACE_ID_UPPER_BOUND || - memcmp_aligned<4>(FIL_PAGE_SPACE_ID + page, + memcmp_aligned<2>(FIL_PAGE_SPACE_ID + page, FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)) { ib::error() << "Inconsistent tablespace ID in file " << name; |