summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kosov <eugene.kosov@mariadb.com>2020-08-04 10:13:35 +0300
committerEugene Kosov <claprix@yandex.ru>2020-08-15 23:05:09 +0300
commit90c8d773ed0ea7de5e735e836e1e33a190711f17 (patch)
tree597f3e9ea756c85b5371aba24e0226807a2291d8
parentb811c6ecc74cc1421eedc92573447768d1eb7980 (diff)
downloadmariadb-git-90c8d773ed0ea7de5e735e836e1e33a190711f17.tar.gz
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
-rw-r--r--storage/innobase/btr/btr0btr.cc1
-rw-r--r--storage/innobase/page/page0page.cc57
2 files changed, 51 insertions, 7 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 786755cb1ab..b29c26b4842 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -5260,7 +5260,6 @@ btr_validate_index(
if (!btr_validate_level(index, trx, n - i, lockout)) {
err = DB_CORRUPTION;
- break;
}
}
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index aab4fbe5d8b..38796d8cb8d 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -2476,6 +2476,7 @@ wrong_page_type:
/* Validate the record list in a loop checking also that
it is consistent with the directory. */
ulint count = 0, data_size = 0, own_count = 1, slot_no = 0;
+ ulint info_bits;
slot_no = 0;
slot = page_dir_get_nth_slot(page, slot_no);
@@ -2499,9 +2500,16 @@ wrong_page_type:
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_get_info_bits(rec, page_is_comp(page))
- & REC_INFO_MIN_REC_FLAG)) {
+ if (info_bits & REC_INFO_MIN_REC_FLAG) {
if (page_has_prev(page)) {
ib::error() << "REC_INFO_MIN_REC_FLAG "
"is set on non-left page";
@@ -2512,8 +2520,7 @@ wrong_page_type:
ib::error() << "REC_INFO_MIN_REC_FLAG "
"is set in a leaf-page record";
ret = false;
- } else if (rec_get_deleted_flag(
- rec, page_is_comp(page))) {
+ } else if (info_bits & REC_INFO_DELETED_FLAG) {
/* If this were a 10.4 metadata
record for index->table->instant
we should not get here in 10.3, because
@@ -2529,13 +2536,51 @@ wrong_page_type:
ib::error() << "Metadata record is missing";
ret = false;
}
- } else if (rec_get_info_bits(rec, page_is_comp(page))
- & REC_INFO_MIN_REC_FLAG) {
+ } else if (info_bits & REC_INFO_MIN_REC_FLAG) {
ib::error() << "REC_INFO_MIN_REC_FLAG record is not "
"first in page";
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 */
if (count >= PAGE_HEAP_NO_USER_LOW
&& !page_rec_is_supremum(rec)) {