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
|
||||
# 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 @@ 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;
|
||||
|
@@ -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
|
||||
|
@@ -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 @@ 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);
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user