Commit 700e0103 authored by Eugene Kosov's avatar Eugene Kosov

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
parent cdd54c85
...@@ -197,37 +197,50 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); ...@@ -197,37 +197,50 @@ extern ulonglong strtoull(const char *str, char **ptr, int base);
} }
# ifdef _MSC_VER # 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 # 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 # endif
template <size_t Alignment> template <size_t Alignment>
inline void *memcpy_aligned(void *dest, const void *src, size_t n) inline void *memcpy_aligned(void *dest, const void *src, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); 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> template <size_t Alignment>
inline void *memmove_aligned(void *dest, const void *src, size_t n) inline void *memmove_aligned(void *dest, const void *src, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); 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> template <size_t Alignment>
inline int memcmp_aligned(const void *s1, const void *s2, size_t n) inline int memcmp_aligned(const void *s1, const void *s2, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); 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> template <size_t Alignment>
inline void *memset_aligned(void *s, int c, size_t n) inline void *memset_aligned(void *s, int c, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); 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 #endif
......
...@@ -1967,9 +1967,8 @@ btr_root_raise_and_insert( ...@@ -1967,9 +1967,8 @@ btr_root_raise_and_insert(
the field only matters on leaf pages, and the root no the field only matters on leaf pages, and the root no
longer is a leaf page. (Older versions of InnoDB did longer is a leaf page. (Older versions of InnoDB did
set PAGE_MAX_TRX_ID on all secondary index pages.) */ set PAGE_MAX_TRX_ID on all secondary index pages.) */
byte* p = static_cast<byte*>( byte* p = my_assume_aligned<8>(
MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID PAGE_HEADER + PAGE_MAX_TRX_ID + root->frame);
+ root->frame, 8));
if (UNIV_LIKELY_NULL(root_page_zip)) { if (UNIV_LIKELY_NULL(root_page_zip)) {
memset_aligned<8>(p, 0, 8); memset_aligned<8>(p, 0, 8);
page_zip_write_header(root_page_zip, p, 8, mtr); page_zip_write_header(root_page_zip, p, 8, mtr);
...@@ -1980,9 +1979,8 @@ btr_root_raise_and_insert( ...@@ -1980,9 +1979,8 @@ btr_root_raise_and_insert(
/* PAGE_ROOT_AUTO_INC is only present in the clustered index /* PAGE_ROOT_AUTO_INC is only present in the clustered index
root page; on other clustered index pages, we want to reserve root page; on other clustered index pages, we want to reserve
the field PAGE_MAX_TRX_ID for future use. */ the field PAGE_MAX_TRX_ID for future use. */
byte* p = static_cast<byte*>( byte* p = my_assume_aligned<8>(
MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID PAGE_HEADER + PAGE_MAX_TRX_ID + new_block->frame);
+ new_block->frame, 8));
if (UNIV_LIKELY_NULL(new_page_zip)) { if (UNIV_LIKELY_NULL(new_page_zip)) {
memset_aligned<8>(p, 0, 8); memset_aligned<8>(p, 0, 8);
page_zip_write_header(new_page_zip, p, 8, mtr); page_zip_write_header(new_page_zip, p, 8, mtr);
......
...@@ -338,7 +338,7 @@ Datafile::read_first_page(bool read_only_mode) ...@@ -338,7 +338,7 @@ Datafile::read_first_page(bool read_only_mode)
} }
if (m_order == 0) { 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 FSP_HEADER_OFFSET + FSP_SPACE_ID
+ m_first_page, 4)) { + m_first_page, 4)) {
ib::error() ib::error()
......
...@@ -298,8 +298,7 @@ log_reserve_and_write_fast( ...@@ -298,8 +298,7 @@ log_reserve_and_write_fast(
*start_lsn = log_sys.lsn; *start_lsn = log_sys.lsn;
memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf + log_sys.buf_free, memcpy(log_sys.buf + log_sys.buf_free, str, len);
str, len);
log_block_set_data_len( log_block_set_data_len(
reinterpret_cast<byte*>(ut_align_down( reinterpret_cast<byte*>(ut_align_down(
......
...@@ -398,8 +398,7 @@ page_rec_is_infimum(const rec_t* rec); ...@@ -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) inline trx_id_t page_get_max_trx_id(const page_t *page)
{ {
static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
const byte *p= static_cast<const byte*> const auto *p= my_assume_aligned<8>(page + PAGE_HEADER + PAGE_MAX_TRX_ID);
(MY_ASSUME_ALIGNED(page + PAGE_HEADER + PAGE_MAX_TRX_ID, 8));
return mach_read_from_8(p); return mach_read_from_8(p);
} }
......
...@@ -355,8 +355,7 @@ log_write_low( ...@@ -355,8 +355,7 @@ log_write_low(
- log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE;
} }
memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf + log_sys.buf_free, memcpy(log_sys.buf + log_sys.buf_free, str, len);
str, len);
str_len -= len; str_len -= len;
str = str + len; str = str + len;
......
...@@ -4518,7 +4518,7 @@ bool fil_node_t::read_page0(bool first) ...@@ -4518,7 +4518,7 @@ bool fil_node_t::read_page0(bool first)
return false; return false;
} }
const ulint space_id = memcmp_aligned<4>( const ulint space_id = memcmp_aligned<2>(
FIL_PAGE_SPACE_ID + page, FIL_PAGE_SPACE_ID + page,
FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4) FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)
? ULINT_UNDEFINED ? ULINT_UNDEFINED
......
...@@ -199,9 +199,8 @@ page_set_max_trx_id( ...@@ -199,9 +199,8 @@ page_set_max_trx_id(
{ {
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); 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 byte *max_trx_id= my_assume_aligned<8>(PAGE_MAX_TRX_ID +
+ PAGE_HEADER PAGE_HEADER + block->frame);
+ block->frame, 8));
if (UNIV_LIKELY_NULL(page_zip)) if (UNIV_LIKELY_NULL(page_zip))
{ {
......
...@@ -84,7 +84,7 @@ static const byte infimum_data[] = { ...@@ -84,7 +84,7 @@ static const byte infimum_data[] = {
0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */ 0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */
}; };
/** Extra bytes and data bytes of a supremum record */ /** 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 */ /* 0x0?, */ /* info_bits=0, n_owned=1..8 */
0x00, 0x0b, /* heap_no=1, status=3 */ 0x00, 0x0b, /* heap_no=1, status=3 */
0x00, 0x00, /* next=0 */ 0x00, 0x00, /* next=0 */
...@@ -4573,8 +4573,7 @@ page_zip_dir_add_slot( ...@@ -4573,8 +4573,7 @@ page_zip_dir_add_slot(
/* Move the uncompressed area backwards to make space /* Move the uncompressed area backwards to make space
for one directory slot. */ for one directory slot. */
memmove_aligned<2>(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, ulint(dir - stored));
ulint(dir - stored));
} }
/***********************************************************//** /***********************************************************//**
......
...@@ -2015,7 +2015,7 @@ PageConverter::update_index_page( ...@@ -2015,7 +2015,7 @@ PageConverter::update_index_page(
inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW
{ {
byte *frame= get_frame(block); 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)) FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, 4))
ib::warn() << "Space id check in the header failed: ignored"; ib::warn() << "Space id check in the header failed: ignored";
else if (!mach_read_from_4(FIL_PAGE_SPACE_ID + frame)) 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 ...@@ -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. */ /* Write space_id to the tablespace header, page 0. */
mach_write_to_4(FIL_PAGE_SPACE_ID + frame, get_space_id()); 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); FIL_PAGE_SPACE_ID + frame, 4);
/* Write back the adjusted flags. */ /* Write back the adjusted flags. */
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame, m_space_flags); mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame, m_space_flags);
......
...@@ -619,7 +619,7 @@ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i) ...@@ -619,7 +619,7 @@ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i)
uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page); uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page);
if (id == 0 || id >= SRV_SPACE_ID_UPPER_BOUND || 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)) FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4))
{ {
ib::error() << "Inconsistent tablespace ID in file " << name; ib::error() << "Inconsistent tablespace ID in file " << name;
......
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