summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kosov <claprix@yandex.ru>2020-01-21 22:22:48 +0800
committerEugene Kosov <claprix@yandex.ru>2020-01-23 00:12:43 +0800
commit700e010309ea9d0f7c32d0973ec88c3140c67956 (patch)
tree28d297e65ea60ffee9cb3c2913040c6c2de2ca04
parentcdd54c852a8491b7e0b949058e0bf7040015f31f (diff)
downloadmariadb-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.h31
-rw-r--r--storage/innobase/btr/btr0btr.cc10
-rw-r--r--storage/innobase/fsp/fsp0file.cc2
-rw-r--r--storage/innobase/include/log0log.ic3
-rw-r--r--storage/innobase/include/page0page.h3
-rw-r--r--storage/innobase/log/log0log.cc3
-rw-r--r--storage/innobase/os/os0file.cc2
-rw-r--r--storage/innobase/page/page0page.cc5
-rw-r--r--storage/innobase/page/page0zip.cc5
-rw-r--r--storage/innobase/row/row0import.cc4
-rw-r--r--storage/innobase/srv/srv0start.cc2
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;