Commit c9498f33 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-18519: Assertion failure in btr_page_reorganize_low()

Even after commit 0b47c126
there are a few ib::fatal() calls in non-debug code
that can be replaced easily.

btr_page_reorganize_low(): On size invariant violation, return
an error code instead of crashing.

btr_check_blob_fil_page_type(): On an invalid page type, report
an error but do not crash.

btr_copy_blob_prefix(): Truncate the output if a page type is invalid.

dict_load_foreign_cols(): On an error, return DB_CORRUPTION instead
of crashing.

fil_space_decrypt_full_crc32(), fil_space_decrypt_for_non_full_checksum():
On error, return DB_DECRYPTION_FAILED instead of crashing.

fil_set_max_space_id_if_bigger(): Replace ib::fatal() with an
equivalent ut_a() assertion.
parent 3d241eb9
...@@ -1305,10 +1305,12 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index, ...@@ -1305,10 +1305,12 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
page_get_max_insert_size_after_reorganize(block->page.frame, 1); page_get_max_insert_size_after_reorganize(block->page.frame, 1);
if (UNIV_UNLIKELY(data_size1 != data_size2 || max1 != max2)) if (UNIV_UNLIKELY(data_size1 != data_size2 || max1 != max2))
ib::fatal() << "Page old data size " << data_size1 {
<< " new data size " << data_size2 sql_print_error("InnoDB: Page old data size %u new data size %u"
<< ", page old max ins size " << max1 ", page old max ins size %zu new max ins size %zu",
<< " new max ins size " << max2; data_size1, data_size2, max1, max2);
return DB_CORRUPTION;
}
/* Restore the cursor position. */ /* Restore the cursor position. */
if (pos) if (pos)
......
...@@ -71,6 +71,7 @@ Created 10/16/1994 Heikki Tuuri ...@@ -71,6 +71,7 @@ Created 10/16/1994 Heikki Tuuri
#ifdef WITH_WSREP #ifdef WITH_WSREP
#include "mysql/service_wsrep.h" #include "mysql/service_wsrep.h"
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
#include "log.h"
/** Buffered B-tree operation types, introduced as part of delete buffering. */ /** Buffered B-tree operation types, introduced as part of delete buffering. */
enum btr_op_t { enum btr_op_t {
...@@ -7196,29 +7197,29 @@ btr_store_big_rec_extern_fields( ...@@ -7196,29 +7197,29 @@ btr_store_big_rec_extern_fields(
} }
/** Check the FIL_PAGE_TYPE on an uncompressed BLOB page. /** Check the FIL_PAGE_TYPE on an uncompressed BLOB page.
@param[in] block uncompressed BLOB page @param block uncompressed BLOB page
@param[in] read true=read, false=purge */ @param op operation
static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read) @return whether the type is invalid */
static bool btr_check_blob_fil_page_type(const buf_block_t& block,
const char *op)
{ {
uint16_t type= fil_page_get_type(block.page.frame); uint16_t type= fil_page_get_type(block.page.frame);
if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB)) if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB));
return; else if (fil_space_t *space= fil_space_t::get(block.page.id().space()))
/* FIXME: take the tablespace as a parameter */
if (fil_space_t *space= fil_space_t::get(block.page.id().space()))
{ {
/* Old versions of InnoDB did not initialize FIL_PAGE_TYPE on BLOB /* Old versions of InnoDB did not initialize FIL_PAGE_TYPE on BLOB
pages. Do not print anything about the type mismatch when reading pages. Do not print anything about the type mismatch when reading
a BLOB page that may be from old versions. */ a BLOB page that may be from old versions. */
if (space->full_crc32() || DICT_TF_HAS_ATOMIC_BLOBS(space->flags)) bool fail= space->full_crc32() || DICT_TF_HAS_ATOMIC_BLOBS(space->flags);
{ if (fail)
ib::fatal() << "FIL_PAGE_TYPE=" << type sql_print_error("InnoDB: FIL_PAGE_TYPE=%u on BLOB %s file %s page %u",
<< (read ? " on BLOB read file " : " on BLOB purge file ") type, op, space->chain.start->name,
<< space->chain.start->name block.page.id().page_no());
<< " page " << block.page.id().page_no();
}
space->release(); space->release();
return fail;
} }
return false;
} }
/*******************************************************************//** /*******************************************************************//**
...@@ -7365,7 +7366,7 @@ btr_free_externally_stored_field( ...@@ -7365,7 +7366,7 @@ btr_free_externally_stored_field(
} }
} else { } else {
ut_ad(!block->page.zip.data); ut_ad(!block->page.zip.data);
btr_check_blob_fil_page_type(*ext_block, false); btr_check_blob_fil_page_type(*ext_block, "purge");
const uint32_t next_page_no = mach_read_from_4( const uint32_t next_page_no = mach_read_from_4(
page + FIL_PAGE_DATA page + FIL_PAGE_DATA
...@@ -7499,14 +7500,12 @@ btr_copy_blob_prefix( ...@@ -7499,14 +7500,12 @@ btr_copy_blob_prefix(
mtr_start(&mtr); mtr_start(&mtr);
block = buf_page_get(id, 0, RW_S_LATCH, &mtr); block = buf_page_get(id, 0, RW_S_LATCH, &mtr);
if (!block) { if (!block || btr_check_blob_fil_page_type(*block, "read")) {
mtr.commit(); mtr.commit();
return copied_len; return copied_len;
} }
page = buf_block_get_frame(block); page = buf_block_get_frame(block);
btr_check_blob_fil_page_type(*block, true);
blob_header = page + offset; blob_header = page + offset;
part_len = btr_blob_get_part_len(blob_header); part_len = btr_blob_get_part_len(blob_header);
copy_len = ut_min(part_len, len - copied_len); copy_len = ut_min(part_len, len - copied_len);
......
...@@ -2657,7 +2657,6 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id) ...@@ -2657,7 +2657,6 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
goto func_exit; goto func_exit;
} }
for (ulint i = 0; i < foreign->n_fields; i++) { for (ulint i = 0; i < foreign->n_fields; i++) {
retry:
ut_a(btr_pcur_is_on_user_rec(&pcur)); ut_a(btr_pcur_is_on_user_rec(&pcur));
const rec_t* rec = btr_pcur_get_rec(&pcur); const rec_t* rec = btr_pcur_get_rec(&pcur);
...@@ -2690,9 +2689,7 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id) ...@@ -2690,9 +2689,7 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
if (rec_get_deleted_flag(rec, 0)) { if (rec_get_deleted_flag(rec, 0)) {
ut_ad(id); ut_ad(id);
next: goto next;
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
goto retry;
} }
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
...@@ -2718,7 +2715,7 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id) ...@@ -2718,7 +2715,7 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
rec, DICT_FLD__SYS_FOREIGN_COLS__REF_COL_NAME, rec, DICT_FLD__SYS_FOREIGN_COLS__REF_COL_NAME,
&ref_col_name_len); &ref_col_name_len);
ib::fatal sout; ib::error sout;
sout << "Unable to load column names for foreign" sout << "Unable to load column names for foreign"
" key '" << foreign->id " key '" << foreign->id
...@@ -2733,6 +2730,9 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id) ...@@ -2733,6 +2730,9 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
sout << "', REF_COL_NAME='"; sout << "', REF_COL_NAME='";
sout.write(ref_col_name, ref_col_name_len); sout.write(ref_col_name, ref_col_name_len);
sout << "')"; sout << "')";
err = DB_CORRUPTION;
break;
} }
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
...@@ -2750,6 +2750,7 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id) ...@@ -2750,6 +2750,7 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
foreign->referenced_col_names[i] = mem_heap_strdupl( foreign->referenced_col_names[i] = mem_heap_strdupl(
foreign->heap, (char*) field, len); foreign->heap, (char*) field, len);
next:
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
} }
func_exit: func_exit:
......
...@@ -665,17 +665,9 @@ static dberr_t fil_space_decrypt_full_crc32( ...@@ -665,17 +665,9 @@ static dberr_t fil_space_decrypt_full_crc32(
(uint) space, offset, lsn); (uint) space, offset, lsn);
if (rc != MY_AES_OK || dstlen != srclen) { if (rc != MY_AES_OK || dstlen != srclen) {
if (rc == -1) {
return DB_DECRYPTION_FAILED; return DB_DECRYPTION_FAILED;
} }
ib::fatal() << "Unable to decrypt data-block "
<< " src: " << src << "srclen: "
<< srclen << " buf: " << dst << "buflen: "
<< dstlen << " return-code: " << rc
<< " Can't continue!";
}
/* Copy only checksum part in the trailer */ /* Copy only checksum part in the trailer */
memcpy(tmp_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM, memcpy(tmp_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM,
src_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM, src_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM,
...@@ -735,20 +727,9 @@ static dberr_t fil_space_decrypt_for_non_full_checksum( ...@@ -735,20 +727,9 @@ static dberr_t fil_space_decrypt_for_non_full_checksum(
space, offset, lsn); space, offset, lsn);
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) { if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
if (rc == -1) {
return DB_DECRYPTION_FAILED; return DB_DECRYPTION_FAILED;
} }
ib::fatal() << "Unable to decrypt data-block "
<< " src: " << static_cast<const void*>(src)
<< "srclen: "
<< srclen << " buf: "
<< static_cast<const void*>(dst) << "buflen: "
<< dstlen << " return-code: " << rc
<< " Can't continue!";
}
/* For compressed tables we do not store the FIL header because /* For compressed tables we do not store the FIL header because
the whole page is not stored to the disk. In compressed tables only the whole page is not stored to the disk. In compressed tables only
the FIL header + compressed (and now encrypted) payload alligned the FIL header + compressed (and now encrypted) payload alligned
......
...@@ -1393,9 +1393,7 @@ fil_set_max_space_id_if_bigger( ...@@ -1393,9 +1393,7 @@ fil_set_max_space_id_if_bigger(
/*===========================*/ /*===========================*/
ulint max_id) /*!< in: maximum known id */ ulint max_id) /*!< in: maximum known id */
{ {
if (max_id >= SRV_SPACE_ID_UPPER_BOUND) { ut_a(max_id < SRV_SPACE_ID_UPPER_BOUND);
ib::fatal() << "Max tablespace id is too high, " << max_id;
}
mysql_mutex_lock(&fil_system.mutex); mysql_mutex_lock(&fil_system.mutex);
......
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