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);
}
# 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
......
......@@ -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);
......
......@@ -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()
......
......@@ -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(
......
......@@ -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);
}
......
......@@ -355,8 +355,7 @@ log_write_low(
- 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;
......
......@@ -4518,7 +4518,7 @@ bool fil_node_t::read_page0(bool first)
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
......
......@@ -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))
{
......
......@@ -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));
}
/***********************************************************//**
......
......@@ -2015,7 +2015,7 @@ PageConverter::update_index_page(
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);
......
......@@ -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);
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;
......
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