diff options
Diffstat (limited to 'storage/xtradb/buf')
-rw-r--r-- | storage/xtradb/buf/buf0buf.cc | 23 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0flu.cc | 34 |
2 files changed, 34 insertions, 23 deletions
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index b6c7126978c..6c6b67ad774 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -635,9 +635,14 @@ buf_page_is_corrupted( checksum_field2 = mach_read_from_4( read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); +#if FIL_PAGE_LSN % 8 +#error "FIL_PAGE_LSN must be 64 bit aligned" +#endif + /* declare empty pages non-corrupted */ if (checksum_field1 == 0 && checksum_field2 == 0 - && mach_read_from_4(read_buf + FIL_PAGE_LSN) == 0) { + && *reinterpret_cast<const ib_uint64_t*>(read_buf + + FIL_PAGE_LSN) == 0) { /* make sure that the page is really empty */ for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) { if (read_buf[i] != 0) { @@ -1697,8 +1702,9 @@ buf_pool_watch_is_sentinel( /****************************************************************//** Add watch for the given page to be read in. Caller must have -appropriate hash_lock for the bpage. This function may release the -hash_lock and reacquire it. +appropriate hash_lock for the bpage and hold the LRU list mutex to avoid a race +condition with buf_LRU_free_page inserting the same page into the page hash. +This function may release the hash_lock and reacquire it. @return NULL if watch set, block if the page is in the buffer pool */ UNIV_INTERN buf_page_t* @@ -1713,6 +1719,8 @@ buf_pool_watch_set( buf_pool_t* buf_pool = buf_pool_get(space, offset); prio_rw_lock_t* hash_lock; + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); + hash_lock = buf_page_hash_lock_get(buf_pool, fold); #ifdef UNIV_SYNC_DEBUG @@ -1781,6 +1789,7 @@ page_found: bpage->space = static_cast<ib_uint32_t>(space); bpage->offset = static_cast<ib_uint32_t>(offset); bpage->buf_fix_count = 1; + bpage->buf_pool_index = buf_pool_index(buf_pool); mutex_exit(&buf_pool->zip_mutex); @@ -2727,9 +2736,11 @@ loop: /* Page not in buf_pool: needs to be read from file */ if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { + mutex_enter(&buf_pool->LRU_list_mutex); rw_lock_x_lock(hash_lock); block = (buf_block_t*) buf_pool_watch_set( space, offset, fold); + mutex_exit(&buf_pool->LRU_list_mutex); if (UNIV_LIKELY_NULL(block)) { /* We can release hash_lock after we @@ -3061,15 +3072,19 @@ got_block: if (buf_LRU_free_page(&fix_block->page, true)) { mutex_exit(fix_mutex); - rw_lock_x_lock(hash_lock); if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { + mutex_enter(&buf_pool->LRU_list_mutex); + rw_lock_x_lock(hash_lock); + /* Set the watch, as it would have been set if the page were not in the buffer pool in the first place. */ block = (buf_block_t*) buf_pool_watch_set( space, offset, fold); + mutex_exit(&buf_pool->LRU_list_mutex); } else { + rw_lock_x_lock(hash_lock); block = (buf_block_t*) buf_page_hash_get_low( buf_pool, space, offset, fold); } diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index dfd7022e71d..cbfba081425 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -829,39 +829,35 @@ buf_flush_init_for_writing( case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: checksum = buf_calc_page_crc32(page); + mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); break; case SRV_CHECKSUM_ALGORITHM_INNODB: case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: checksum = (ib_uint32_t) buf_calc_page_new_checksum(page); + mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); + checksum = (ib_uint32_t) buf_calc_page_old_checksum(page); break; case SRV_CHECKSUM_ALGORITHM_NONE: case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: checksum = BUF_NO_CHECKSUM_MAGIC; + mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); break; /* no default so the compiler will emit a warning if new enum is added and not handled here */ } - mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); - - /* We overwrite the first 4 bytes of the end lsn field to store - the old formula checksum. Since it depends also on the field - FIL_PAGE_SPACE_OR_CHKSUM, it has to be calculated after storing the - new formula checksum. */ - - if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB - || srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB) { + /* With the InnoDB checksum, we overwrite the first 4 bytes of + the end lsn field to store the old formula checksum. Since it + depends also on the field FIL_PAGE_SPACE_OR_CHKSUM, it has to + be calculated after storing the new formula checksum. - checksum = (ib_uint32_t) buf_calc_page_old_checksum(page); - - /* In other cases we use the value assigned from above. - If CRC32 is used then it is faster to use that checksum - (calculated above) instead of calculating another one. - We can afford to store something other than - buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in - this field because the file will not be readable by old - versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */ - } + In other cases we write the same value to both fields. + If CRC32 is used then it is faster to use that checksum + (calculated above) instead of calculating another one. + We can afford to store something other than + buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in + this field because the file will not be readable by old + versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, checksum); |