summaryrefslogtreecommitdiff
path: root/storage/xtradb/buf
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/buf')
-rw-r--r--storage/xtradb/buf/buf0buf.cc23
-rw-r--r--storage/xtradb/buf/buf0flu.cc34
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);