Skip to content

Commit

Permalink
MDEV-21171 InnoDB is unnecessarily resetting FIL_PAGE_TYPE for full_c…
Browse files Browse the repository at this point in the history
…rc32 files

Before commit c0f47a4 (MDEV-12026)
introduced the innodb_checksum_algorithm=full_crc32 format,
it was impossible to tell if InnoDB data files contained garbage in
the FIL_PAGE_TYPE header field (and possibly other fields).
This is because before commit 3926673
in MySQL 5.1.48, InnoDB would write uninitialized data to some fields,
and because there was no way to tell with which InnoDB version a data
file was created.

If fil_space_t::full_crc32() holds, the data file cannot contain
uninitialized garbage or invalid FIL_PAGE_TYPE, and thus
fil_block_check_type() should not be invoked to correct anything.
  • Loading branch information
dr-m committed Nov 28, 2019
1 parent 576e85a commit 4beace3
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 32 deletions.
37 changes: 24 additions & 13 deletions storage/innobase/fsp/fsp0fsp.cc
Expand Up @@ -1012,7 +1012,7 @@ fsp_fill_free_list(
buf_block_t* desc_block = NULL;
descr = xdes_get_descriptor_with_space_hdr(
header, space, i, mtr, init_space, &desc_block);
if (desc_block != NULL) {
if (desc_block && !space->full_crc32()) {
fil_block_check_type(
*desc_block, FIL_PAGE_TYPE_XDES, mtr);
}
Expand Down Expand Up @@ -1070,7 +1070,7 @@ fsp_alloc_free_extent(
descr = xdes_get_descriptor_with_space_hdr(
header, space, hint, mtr, false, &desc_block);

if (desc_block != NULL) {
if (desc_block && !space->full_crc32()) {
fil_block_check_type(*desc_block, FIL_PAGE_TYPE_XDES, mtr);
}

Expand Down Expand Up @@ -1597,7 +1597,9 @@ fsp_alloc_seg_inode(

block = buf_page_get(page_id, space->zip_size(), RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
fil_block_check_type(*block, FIL_PAGE_INODE, mtr);
if (!space->full_crc32()) {
fil_block_check_type(*block, FIL_PAGE_INODE, mtr);
}

page = buf_block_get_frame(block);

Expand Down Expand Up @@ -1898,12 +1900,13 @@ fseg_create(

header = byte_offset + buf_block_get_frame(block);

const ulint type = space->id == TRX_SYS_SPACE
&& page == TRX_SYS_PAGE_NO
? FIL_PAGE_TYPE_TRX_SYS
: FIL_PAGE_TYPE_SYS;

fil_block_check_type(*block, type, mtr);
if (!space->full_crc32()) {
fil_block_check_type(*block, space->id == TRX_SYS_SPACE
&& page == TRX_SYS_PAGE_NO
? FIL_PAGE_TYPE_TRX_SYS
: FIL_PAGE_TYPE_SYS,
mtr);
}
}

if (!has_done_reservation
Expand Down Expand Up @@ -2452,7 +2455,9 @@ fseg_alloc_free_page_general(
space = mtr_x_lock_space(space_id, mtr);
inode = fseg_inode_get(seg_header, space_id, space->zip_size(),
mtr, &iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
if (!space->full_crc32()) {
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
}

if (!has_done_reservation
&& !fsp_reserve_free_extents(&n_reserved, space, 2,
Expand Down Expand Up @@ -2872,7 +2877,9 @@ fseg_free_page_func(
seg_inode = fseg_inode_get(seg_header, space->id, space->zip_size(),
mtr,
&iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
if (!space->full_crc32()) {
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
}

fseg_free_page_low(seg_inode, space, offset, ahi, log, mtr);

Expand Down Expand Up @@ -3047,7 +3054,9 @@ fseg_free_step_func(
DBUG_RETURN(TRUE);
}

fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
if (!space->full_crc32()) {
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
}
descr = fseg_get_first_extent(inode, space, mtr);

if (descr != NULL) {
Expand Down Expand Up @@ -3113,7 +3122,9 @@ fseg_free_step_not_header_func(

inode = fseg_inode_get(header, space_id, space->zip_size(), mtr,
&iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
if (!space->full_crc32()) {
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
}

descr = fseg_get_first_extent(inode, space, mtr);

Expand Down
29 changes: 12 additions & 17 deletions storage/innobase/include/trx0sys.h
Expand Up @@ -68,17 +68,13 @@ trx_sys_rseg_find_free(const buf_block_t* sys_header);
@param[in] rw whether to lock the page for writing
@return the TRX_SYS page
@retval NULL if the page cannot be read */
inline
buf_block_t*
trx_sysf_get(mtr_t* mtr, bool rw = true)
inline buf_block_t *trx_sysf_get(mtr_t* mtr, bool rw= true)
{
buf_block_t* block = buf_page_get(
page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
0, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
if (block) {
buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
}
return block;
buf_block_t* block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
0, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
if (block)
buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
return block;
}

#ifdef UNIV_DEBUG
Expand Down Expand Up @@ -200,14 +196,13 @@ trx_sysf_rseg_get_space(const buf_block_t* sys_header, ulint rseg_id)
@param[in] sys_header TRX_SYS page
@param[in] rseg_id rollback segment identifier
@return undo page number */
inline
uint32_t
trx_sysf_rseg_get_page_no(const buf_block_t* sys_header, ulint rseg_id)
inline uint32_t
trx_sysf_rseg_get_page_no(const buf_block_t *sys_header, ulint rseg_id)
{
ut_ad(rseg_id < TRX_SYS_N_RSEGS);
return mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE
+ sys_header->frame);
ut_ad(rseg_id < TRX_SYS_N_RSEGS);
return mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO +
rseg_id * TRX_SYS_RSEG_SLOT_SIZE +
sys_header->frame);
}

/** Maximum length of MySQL binlog file name, in bytes.
Expand Down
5 changes: 3 additions & 2 deletions storage/innobase/srv/srv0start.cc
Expand Up @@ -2104,8 +2104,9 @@ dberr_t srv_start(bool create_new_db)
}

/* Validate a few system page types that were left
uninitialized by older versions of MySQL. */
if (!high_level_read_only) {
uninitialized before MySQL or MariaDB 5.5. */
if (!high_level_read_only
&& !fil_system.sys_space->full_crc32()) {
buf_block_t* block;
mtr.start();
/* Bitmap page types will be reset in
Expand Down

0 comments on commit 4beace3

Please sign in to comment.