Commit 90c8d773 authored by Eugene Kosov's avatar Eugene Kosov Committed by Eugene Kosov

MDEV-21251 CHECK TABLE fails to check info_bits of records

btr_validate_index(): do not stop checking after some level failed.
That way it'll become possible to see errors in leaf pages even when
uppers layers are corrupted too.

page_validate(): check info_bits and status_bits more
parent b811c6ec
...@@ -5260,7 +5260,6 @@ btr_validate_index( ...@@ -5260,7 +5260,6 @@ btr_validate_index(
if (!btr_validate_level(index, trx, n - i, lockout)) { if (!btr_validate_level(index, trx, n - i, lockout)) {
err = DB_CORRUPTION; err = DB_CORRUPTION;
break;
} }
} }
......
...@@ -2476,6 +2476,7 @@ bool page_validate(const page_t* page, const dict_index_t* index) ...@@ -2476,6 +2476,7 @@ bool page_validate(const page_t* page, const dict_index_t* index)
/* Validate the record list in a loop checking also that /* Validate the record list in a loop checking also that
it is consistent with the directory. */ it is consistent with the directory. */
ulint count = 0, data_size = 0, own_count = 1, slot_no = 0; ulint count = 0, data_size = 0, own_count = 1, slot_no = 0;
ulint info_bits;
slot_no = 0; slot_no = 0;
slot = page_dir_get_nth_slot(page, slot_no); slot = page_dir_get_nth_slot(page, slot_no);
...@@ -2499,9 +2500,16 @@ bool page_validate(const page_t* page, const dict_index_t* index) ...@@ -2499,9 +2500,16 @@ bool page_validate(const page_t* page, const dict_index_t* index)
goto next_rec; goto next_rec;
} }
info_bits = rec_get_info_bits(rec, page_is_comp(page));
if (info_bits
& ~(REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)) {
ib::error() << "info_bits has an incorrect value "
<< info_bits;
ret = false;
}
if (rec == first_rec) { if (rec == first_rec) {
if ((rec_get_info_bits(rec, page_is_comp(page)) if (info_bits & REC_INFO_MIN_REC_FLAG) {
& REC_INFO_MIN_REC_FLAG)) {
if (page_has_prev(page)) { if (page_has_prev(page)) {
ib::error() << "REC_INFO_MIN_REC_FLAG " ib::error() << "REC_INFO_MIN_REC_FLAG "
"is set on non-left page"; "is set on non-left page";
...@@ -2512,8 +2520,7 @@ bool page_validate(const page_t* page, const dict_index_t* index) ...@@ -2512,8 +2520,7 @@ bool page_validate(const page_t* page, const dict_index_t* index)
ib::error() << "REC_INFO_MIN_REC_FLAG " ib::error() << "REC_INFO_MIN_REC_FLAG "
"is set in a leaf-page record"; "is set in a leaf-page record";
ret = false; ret = false;
} else if (rec_get_deleted_flag( } else if (info_bits & REC_INFO_DELETED_FLAG) {
rec, page_is_comp(page))) {
/* If this were a 10.4 metadata /* If this were a 10.4 metadata
record for index->table->instant record for index->table->instant
we should not get here in 10.3, because we should not get here in 10.3, because
...@@ -2529,13 +2536,51 @@ bool page_validate(const page_t* page, const dict_index_t* index) ...@@ -2529,13 +2536,51 @@ bool page_validate(const page_t* page, const dict_index_t* index)
ib::error() << "Metadata record is missing"; ib::error() << "Metadata record is missing";
ret = false; ret = false;
} }
} else if (rec_get_info_bits(rec, page_is_comp(page)) } else if (info_bits & REC_INFO_MIN_REC_FLAG) {
& REC_INFO_MIN_REC_FLAG) {
ib::error() << "REC_INFO_MIN_REC_FLAG record is not " ib::error() << "REC_INFO_MIN_REC_FLAG record is not "
"first in page"; "first in page";
ret = false; ret = false;
} }
if (page_is_comp(page)) {
const rec_comp_status_t status = rec_get_status(rec);
if (status != REC_STATUS_ORDINARY
&& status != REC_STATUS_NODE_PTR
&& status != REC_STATUS_INFIMUM
&& status != REC_STATUS_SUPREMUM
&& status != REC_STATUS_COLUMNS_ADDED) {
ib::error() << "impossible record status "
<< status;
ret = false;
} else if (page_rec_is_infimum(rec)) {
if (status != REC_STATUS_INFIMUM) {
ib::error()
<< "infimum record has status "
<< status;
ret = false;
}
} else if (page_rec_is_supremum(rec)) {
if (status != REC_STATUS_SUPREMUM) {
ib::error() << "supremum record has "
"status "
<< status;
ret = false;
}
} else if (!page_is_leaf(page)) {
if (status != REC_STATUS_NODE_PTR) {
ib::error() << "node ptr record has "
"status "
<< status;
ret = false;
}
} else if (!index->is_instant()
&& status == REC_STATUS_COLUMNS_ADDED) {
ib::error() << "instantly added record in a "
"non-instant index";
ret = false;
}
}
/* Check that the records are in the ascending order */ /* Check that the records are in the ascending order */
if (count >= PAGE_HEAP_NO_USER_LOW if (count >= PAGE_HEAP_NO_USER_LOW
&& !page_rec_is_supremum(rec)) { && !page_rec_is_supremum(rec)) {
......
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