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

MDEV-20813: Do not rotate keys for unallocated pages

fil_crypt_rotate_page(): Skip the key rotation for pages that carry 0
in FIL_PAGE_TYPE. This avoids not only unnecessary writes, but also
failures of the recently added debug assertion in
buf_flush_init_for_writing() that the FIL_PAGE_TYPE should be nonzero.

Note: the debug assertion can fail if the file was originally created
before MySQL 5.5. In old InnoDB versions, FIL_PAGE_TYPE was only
initialized for B-tree pages, to FIL_PAGE_INDEX. For any other pages,
the field could be garbage, including FIL_PAGE_INDEX. In MariaDB 10.2
and later, buf_flush_init_for_writing() would initialize the
FIL_PAGE_TYPE on such old pages, but only after passing the debug
assertion that insists that pages have a nonzero FIL_PAGE_TYPE.
Thus, the debug assertion at the start of buf_flush_init_for_writing()
can fail when upgrading from very old debug files. This assertion is
only present in debug builds, not release builds.
parent 4f9f3f19
......@@ -1773,8 +1773,6 @@ fil_crypt_rotate_page(
return;
}
ut_d(const bool was_free = fseg_page_is_free(space, offset));
mtr_t mtr;
mtr.start();
if (buf_block_t* block = fil_crypt_get_page_throttle(state,
......@@ -1789,9 +1787,9 @@ fil_crypt_rotate_page(
if (space->is_stopping()) {
/* The tablespace is closing (in DROP TABLE or
TRUNCATE TABLE or similar): avoid further access */
} else if (!*reinterpret_cast<uint32_t*>(FIL_PAGE_OFFSET
+ frame)) {
/* It looks like this page was never
} else if (!kv && !*reinterpret_cast<uint16_t*>
(&frame[FIL_PAGE_TYPE])) {
/* It looks like this page is not
allocated. Because key rotation is accessing
pages in a pattern that is unlike the normal
B-tree and undo log access pattern, we cannot
......@@ -1801,9 +1799,20 @@ fil_crypt_rotate_page(
tablespace latch before acquiring block->lock,
then the fseg_page_is_free() information
could be stale already. */
ut_ad(was_free);
ut_ad(kv == 0);
ut_ad(page_get_space_id(frame) == 0);
/* If the data file was originally created
before MariaDB 10.0 or MySQL 5.6, some
allocated data pages could carry 0 in
FIL_PAGE_TYPE. The FIL_PAGE_TYPE on those
pages will be updated in
buf_flush_init_for_writing() when the page
is modified the next time.
Also, when the doublewrite buffer pages are
allocated on bootstrap in a non-debug build,
some dummy pages will be allocated, with 0 in
the FIL_PAGE_TYPE. Those pages should be
skipped from key rotation forever. */
} else if (fil_crypt_needs_rotation(
crypt_data,
kv,
......
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