mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
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
This commit is contained in:
@@ -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(
|
|||||||
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(
|
|||||||
/* 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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(
|
|||||||
|
|
||||||
*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);
|
|||||||
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 @@ part_loop:
|
|||||||
- 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 @@ corrupted:
|
|||||||
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(
|
|||||||
{
|
{
|
||||||
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[] = {
|
|||||||
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(
|
|||||||
|
|
||||||
/* 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 @@ clear_page_max_trx_id:
|
|||||||
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
|
|||||||
|
|
||||||
/* 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 @@ err_exit:
|
|||||||
|
|
||||||
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;
|
||||||
|
Reference in New Issue
Block a user