diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 87ff74a7d51..3bcc5d835e5 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -19,8 +19,9 @@ call mtr.add_suppression("InnoDB: New log files created"); call mtr.add_suppression("InnoDB: Cannot create doublewrite buffer: the first file in innodb_data_file_path must be at least (3|6|12)M\\."); call mtr.add_suppression("InnoDB: Database creation was aborted"); call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registration as a STORAGE ENGINE failed)"); -call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile.*"); -call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: .*"); +call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); +call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); +call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); --enable_query_log --source include/restart_mysqld.inc diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index c21a75687e6..a005ae5dff4 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -341,7 +341,17 @@ Datafile::read_first_page(bool read_only_mode) } if (m_order == 0) { - m_space_id = fsp_header_get_space_id(m_first_page); + if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + m_first_page, + FSP_HEADER_OFFSET + FSP_SPACE_ID + + m_first_page, 4)) { + ib::error() + << "Inconsistent tablespace ID in " + << m_filepath; + return DB_CORRUPTION; + } + + m_space_id = mach_read_from_4(FIL_PAGE_SPACE_ID + + m_first_page); m_flags = fsp_header_get_flags(m_first_page); if (!fil_space_t::is_valid_flags(m_flags, m_space_id)) { ulint cflags = fsp_flags_convert_from_101(m_flags); diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 25fd9b0aabf..260de1eadea 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -612,33 +612,6 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr) } } -/**********************************************************************//** -Reads the space id from the first page of a tablespace. -@return space id, ULINT UNDEFINED if error */ -ulint -fsp_header_get_space_id( -/*====================*/ - const page_t* page) /*!< in: first page of a tablespace */ -{ - ulint fsp_id; - ulint id; - - fsp_id = mach_read_from_4(FSP_HEADER_OFFSET + page + FSP_SPACE_ID); - - id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - - DBUG_EXECUTE_IF("fsp_header_get_space_id_failure", - id = ULINT_UNDEFINED;); - - if (id != fsp_id) { - ib::error() << "Space ID in fsp header is " << fsp_id - << ", but in the page header it is " << id << "."; - return(ULINT_UNDEFINED); - } - - return(id); -} - /** Try to extend a single-table tablespace so that a page would fit in the data file. @param[in,out] space tablespace diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 05494553177..48a1ef5de8b 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -302,14 +302,6 @@ inline bool xdes_is_free(const xdes_t *descr, ulint offset) #ifndef UNIV_INNOCHECKSUM /* @} */ -/**********************************************************************//** -Reads the space id from the first page of a tablespace. -@return space id, ULINT UNDEFINED if error */ -ulint -fsp_header_get_space_id( -/*====================*/ - const page_t* page); /*!< in: first page of a tablespace */ - /** Read a tablespace header field. @param[in] page first page of a tablespace @param[in] field the header field diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index d4bf270217b..4b43b1f50b0 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4464,17 +4464,20 @@ bool fil_node_t::read_page0(bool first) return false; } - byte* buf2 = static_cast(ut_malloc_nokey(2 * psize)); - - /* Align the memory for file i/o if we might have O_DIRECT set */ - byte* page = static_cast(ut_align(buf2, psize)); - IORequest request(IORequest::READ); - if (os_file_read(request, handle, page, 0, psize) != DB_SUCCESS) { + page_t *page= static_cast(aligned_malloc(psize, psize)); + if (os_file_read(IORequestRead, handle, page, 0, psize) + != DB_SUCCESS) { ib::error() << "Unable to read first page of file " << name; - ut_free(buf2); +corrupted: + aligned_free(page); return false; } - const ulint space_id = fsp_header_get_space_id(page); + + const ulint space_id = memcmp_aligned<4>( + FIL_PAGE_SPACE_ID + page, + FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4) + ? ULINT_UNDEFINED + : mach_read_from_4(FIL_PAGE_SPACE_ID + page); ulint flags = fsp_header_get_flags(page); const ulint size = fsp_header_get_field(page, FSP_SIZE); const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT); @@ -4489,8 +4492,7 @@ invalid: << ib::hex(space->flags) << " but found " << ib::hex(flags) << " in the file " << name; - ut_free(buf2); - return false; + goto corrupted; } ulint cf = cflags & ~FSP_FLAGS_MEM_MASK; @@ -4511,7 +4513,7 @@ invalid: space->crypt_data = fil_space_read_crypt_data( fil_space_t::zip_size(flags), page); } - ut_free(buf2); + aligned_free(page); if (UNIV_UNLIKELY(space_id != space->id)) { ib::error() << "Expected tablespace id " << space->id diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 321c7d21a6c..beca1cffc10 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1903,36 +1903,25 @@ clear_page_max_trx_id: /** Validate the space flags and update tablespace header page. @param block block read from file, not from the buffer pool. @retval DB_SUCCESS or error code */ -inline -dberr_t -PageConverter::update_header( - buf_block_t* block) UNIV_NOTHROW +inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW { - /* Check for valid header */ - switch (fsp_header_get_space_id(get_frame(block))) { - case 0: - return(DB_CORRUPTION); - case ULINT_UNDEFINED: - ib::warn() << "Space id check in the header failed: ignored"; - } + byte *frame= get_frame(block); + if (memcmp_aligned<4>(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)) + return DB_CORRUPTION; - memset(get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,0,8); + memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8); - /* Write back the adjusted flags. */ - mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS - + get_frame(block), m_space_flags); + /* 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, + 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); - /* Write space_id to the tablespace header, page 0. */ - mach_write_to_4( - get_frame(block) + FSP_HEADER_OFFSET + FSP_SPACE_ID, - get_space_id()); - - /* This is on every page in the tablespace. */ - mach_write_to_4( - get_frame(block) + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, - get_space_id()); - - return(DB_SUCCESS); + return DB_SUCCESS; } /** Update the page, set the space id, max trx id and index id. diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 0556bcd65bb..3ea2f967b68 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -599,7 +599,6 @@ static ulint trx_rseg_get_n_undo_tablespaces() @retval 0 on failure */ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i) { - pfs_os_file_t fh; bool success; char undo_name[sizeof "innodb_undo000"]; ulint space_id= 0; @@ -620,10 +619,11 @@ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i) } } - fh = os_file_create( - innodb_data_file_key, name, OS_FILE_OPEN - | OS_FILE_ON_ERROR_NO_EXIT | OS_FILE_ON_ERROR_SILENT, - OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success); + pfs_os_file_t fh= os_file_create(innodb_data_file_key, name, OS_FILE_OPEN | + OS_FILE_ON_ERROR_NO_EXIT | + OS_FILE_ON_ERROR_SILENT, + OS_FILE_AIO, OS_DATA_FILE, + srv_read_only_mode, &success); if (!success) return 0; @@ -644,11 +644,20 @@ err_exit: return err; } - fsp_flags= mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - uint32_t id= fsp_header_get_space_id(page); + uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page); if (id == 0 || id >= SRV_LOG_SPACE_FIRST_ID || - buf_page_is_corrupted(false, page, fsp_flags)) + memcmp_aligned<4>(FIL_PAGE_SPACE_ID + page, + FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)) { + ib::error() << "Inconsistent tablespace ID in file " << name; + err= DB_CORRUPTION; + goto err_exit; + } + + fsp_flags= mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + if (buf_page_is_corrupted(false, page, fsp_flags)) + { + ib::error() << "Checksum mismatch in the first page of file " << name; err= DB_CORRUPTION; goto err_exit; }