Commit e974b564 authored by Jan Lindström's avatar Jan Lindström

MDEV-6512: InnoDB: Assertion failure in thread 4537024512 in file

buf0buf.cc line 2642.

Analysis: innodb_compression_algorithm is a global variable and
can change while we are building page compressed page. This could
lead page corruption.

Fix: Cache innodb_compression_algorithm on local variable before
doing any compression or page formating to avoid concurrent
change. Improved page verification on debug builds.
parent 4e3796d7
......@@ -830,6 +830,11 @@ buf_page_print(
mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
mach_read_from_4(read_buf
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
ulint page_type = mach_read_from_4(read_buf + FIL_PAGE_TYPE);
fprintf(stderr, "InnoDB: page type %ld meaning %s\n", page_type,
fil_get_page_type_name(page_type));
}
#ifndef UNIV_HOTBACKUP
......
......@@ -6697,3 +6697,46 @@ fil_space_name(
{
return (space->name);
}
/*******************************************************************//**
Return page type name */
char*
fil_get_page_type_name(
/*===================*/
ulint page_type) /*!< in: FIL_PAGE_TYPE */
{
switch(page_type) {
case FIL_PAGE_PAGE_COMPRESSED:
return "PAGE_COMPRESSED";
case FIL_PAGE_INDEX:
return "INDEX";
case FIL_PAGE_UNDO_LOG:
return "UNDO LOG";
case FIL_PAGE_INODE:
return "INODE";
case FIL_PAGE_IBUF_FREE_LIST:
return "IBUF_FREE_LIST";
case FIL_PAGE_TYPE_ALLOCATED:
return "ALLOCATED";
case FIL_PAGE_IBUF_BITMAP:
return "IBUF_BITMAP";
case FIL_PAGE_TYPE_SYS:
return "SYS";
case FIL_PAGE_TYPE_TRX_SYS:
return "TRX_SYS";
case FIL_PAGE_TYPE_FSP_HDR:
return "FSP_HDR";
case FIL_PAGE_TYPE_XDES:
return "XDES";
case FIL_PAGE_TYPE_BLOB:
return "BLOB";
case FIL_PAGE_TYPE_ZBLOB:
return "ZBLOB";
case FIL_PAGE_TYPE_ZBLOB2:
return "ZBLOB2";
case FIL_PAGE_TYPE_COMPRESSED:
return "ORACLE PAGE COMPRESSED";
default:
return "PAGE TYPE CORRUPTED";
}
}
......@@ -268,6 +268,9 @@ fil_compress_page(
int level = 0;
ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
ulint write_size=0;
ulint comp_method = innodb_compression_algorithm; /* Cache to avoid
change during
function execution */
ut_ad(buf);
ut_ad(out_buf);
......@@ -295,7 +298,7 @@ fil_compress_page(
write_size = UNIV_PAGE_SIZE - header_len;
switch(innodb_compression_algorithm) {
switch(comp_method) {
#ifdef HAVE_LZ4
case PAGE_LZ4_ALGORITHM:
err = LZ4_compress_limitedOutput((const char *)buf,
......@@ -346,6 +349,10 @@ fil_compress_page(
(size_t)&write_size);
if (err != LZMA_OK || write_size > UNIV_PAGE_SIZE-header_len) {
fprintf(stderr,
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
space_id, fil_space_name(space), len, err, write_size);
srv_stats.pages_page_compression_error.inc();
*out_len = len;
return (buf);
......@@ -367,6 +374,9 @@ fil_compress_page(
0);
if (err != BZ_OK || write_size > UNIV_PAGE_SIZE-header_len) {
fprintf(stderr,
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
space_id, fil_space_name(space), len, err, write_size);
srv_stats.pages_page_compression_error.inc();
*out_len = len;
return (buf);
......@@ -408,7 +418,7 @@ fil_compress_page(
/* Set up the correct page type */
mach_write_to_2(out_buf+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED);
/* Set up the flush lsn to be compression algorithm */
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, innodb_compression_algorithm);
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, comp_method);
/* Set up the actual payload lenght */
mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size);
......@@ -417,7 +427,25 @@ fil_compress_page(
ut_ad(fil_page_is_compressed(out_buf));
ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC);
ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size);
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)innodb_compression_algorithm);
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)comp_method);
/* Verify that page can be decompressed */
{
byte *comp_page;
byte *uncomp_page;
comp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
uncomp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
memcpy(comp_page, out_buf, UNIV_PAGE_SIZE);
fil_decompress_page(uncomp_page, comp_page, len, NULL);
if(buf_page_is_corrupted(false, uncomp_page, 0)) {
buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
ut_error;
}
ut_free(comp_page);
ut_free(uncomp_page);
}
#endif /* UNIV_DEBUG */
write_size+=header_len;
......@@ -481,7 +509,7 @@ fil_decompress_page(
fprintf(stderr,
"InnoDB: Note: FIL: Compression buffer not given, allocating...\n");
#endif /* UNIV_PAGECOMPRESS_DEBUG */
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE));
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
} else {
in_buf = page_buf;
}
......
......@@ -1073,4 +1073,12 @@ fil_space_name(
/*===========*/
fil_space_t* space); /*!< in: space */
#endif
/*******************************************************************//**
Return page type name */
char*
fil_get_page_type_name(
/*===================*/
ulint page_type); /*!< in: FIL_PAGE_TYPE */
#endif /* fil0fil_h */
......@@ -865,6 +865,11 @@ buf_page_print(
mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
mach_read_from_4(read_buf
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
ulint page_type = mach_read_from_4(read_buf + FIL_PAGE_TYPE);
fprintf(stderr, "InnoDB: page type %ld meaning %s\n", page_type,
fil_get_page_type_name(page_type));
}
#ifndef UNIV_HOTBACKUP
......
......@@ -6823,3 +6823,46 @@ fil_space_name(
{
return (space->name);
}
/*******************************************************************//**
Return page type name */
char*
fil_get_page_type_name(
/*===================*/
ulint page_type) /*!< in: FIL_PAGE_TYPE */
{
switch(page_type) {
case FIL_PAGE_PAGE_COMPRESSED:
return "PAGE_COMPRESSED";
case FIL_PAGE_INDEX:
return "INDEX";
case FIL_PAGE_UNDO_LOG:
return "UNDO LOG";
case FIL_PAGE_INODE:
return "INODE";
case FIL_PAGE_IBUF_FREE_LIST:
return "IBUF_FREE_LIST";
case FIL_PAGE_TYPE_ALLOCATED:
return "ALLOCATED";
case FIL_PAGE_IBUF_BITMAP:
return "IBUF_BITMAP";
case FIL_PAGE_TYPE_SYS:
return "SYS";
case FIL_PAGE_TYPE_TRX_SYS:
return "TRX_SYS";
case FIL_PAGE_TYPE_FSP_HDR:
return "FSP_HDR";
case FIL_PAGE_TYPE_XDES:
return "XDES";
case FIL_PAGE_TYPE_BLOB:
return "BLOB";
case FIL_PAGE_TYPE_ZBLOB:
return "ZBLOB";
case FIL_PAGE_TYPE_ZBLOB2:
return "ZBLOB2";
case FIL_PAGE_TYPE_COMPRESSED:
return "ORACLE PAGE COMPRESSED";
default:
return "PAGE TYPE CORRUPTED";
}
}
......@@ -268,7 +268,9 @@ fil_compress_page(
int level = 0;
ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
ulint write_size=0;
ulint comp_method = innodb_compression_algorithm; /* Cache to avoid
change during
function execution */
ut_ad(buf);
ut_ad(out_buf);
ut_ad(len);
......@@ -295,7 +297,7 @@ fil_compress_page(
write_size = UNIV_PAGE_SIZE - header_len;
switch(innodb_compression_algorithm) {
switch(comp_method) {
#ifdef HAVE_LZ4
case PAGE_LZ4_ALGORITHM:
err = LZ4_compress_limitedOutput((const char *)buf,
......@@ -346,6 +348,9 @@ fil_compress_page(
(size_t)&write_size);
if (err != LZMA_OK || write_size > UNIV_PAGE_SIZE-header_len) {
fprintf(stderr,
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
space_id, fil_space_name(space), len, err, write_size);
srv_stats.pages_page_compression_error.inc();
*out_len = len;
return (buf);
......@@ -367,6 +372,9 @@ fil_compress_page(
0);
if (err != BZ_OK || write_size > UNIV_PAGE_SIZE-header_len) {
fprintf(stderr,
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
space_id, fil_space_name(space), len, err, write_size);
srv_stats.pages_page_compression_error.inc();
*out_len = len;
return (buf);
......@@ -407,7 +415,7 @@ fil_compress_page(
/* Set up the correct page type */
mach_write_to_2(out_buf+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED);
/* Set up the flush lsn to be compression algorithm */
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, innodb_compression_algorithm);
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, comp_method);
/* Set up the actual payload lenght */
mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size);
......@@ -416,7 +424,25 @@ fil_compress_page(
ut_ad(fil_page_is_compressed(out_buf));
ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC);
ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size);
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)innodb_compression_algorithm);
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)comp_method);
/* Verify that page can be decompressed */
{
byte *comp_page;
byte *uncomp_page;
comp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
uncomp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
memcpy(comp_page, out_buf, UNIV_PAGE_SIZE);
fil_decompress_page(uncomp_page, comp_page, len, NULL);
if(buf_page_is_corrupted(false, uncomp_page, 0)) {
buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
ut_error;
}
ut_free(comp_page);
ut_free(uncomp_page);
}
#endif /* UNIV_DEBUG */
write_size+=header_len;
......@@ -480,7 +506,7 @@ fil_decompress_page(
fprintf(stderr,
"InnoDB: Note: FIL: Compression buffer not given, allocating...\n");
#endif /* UNIV_PAGECOMPRESS_DEBUG */
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE));
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
} else {
in_buf = page_buf;
}
......
......@@ -1117,4 +1117,11 @@ os_file_handle_error_no_exit(
const char* file, /*!< in: file name */
const ulint line); /*!< in: line */
/*******************************************************************//**
Return page type name */
char*
fil_get_page_type_name(
/*===================*/
ulint page_type); /*!< in: FIL_PAGE_TYPE */
#endif /* fil0fil_h */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment