Commit 2151aed4 authored by Marko Mäkelä's avatar Marko Mäkelä

Follow-up fix to MDEV-12026: FIL_SPACE_FLAGS trump fil_space_t::flags

Whenever we are reading the first page of a data file, we may have to
adjust the provisionally created fil_space_t::flags to match what is
actually inside the data files. In this way, we will never accidentally
change the format of a data file.

fil_node_t::read_page0(): After validating the FIL_SPACE_FLAGS,
always assign them to space->flags.

btr_root_adjust_on_import(), Datafile::validate_to_dd(),
fil_space_for_table_exists_in_mem(): Adapt to the fix
in fil_node_t::read_page0().

fsp_flags_try_adjust(): Skip the adjustment if full_crc32 is being
used. This adjustment was introduced in MDEV-11623 for upgrading
from MariaDB 10.1.0 to 10.1.20, which used an accidentally changed
format of FIL_SPACE_FLAGS. MariaDB before 10.4.3 never set the
flag that now indicates the full_crc32 format.
parent 9c729936
......@@ -392,9 +392,21 @@ btr_root_adjust_on_import(
} else {
/* Check that the table flags and the tablespace
flags match. */
err = (dict_tf_to_fsp_flags(table->flags)
== table->space->flags)
? DB_SUCCESS : DB_CORRUPTION;
ulint tf = dict_tf_to_fsp_flags(table->flags);
ulint sf = table->space->flags;
sf &= ~FSP_FLAGS_MEM_MASK;
tf &= ~FSP_FLAGS_MEM_MASK;
if (fil_space_t::is_flags_equal(tf, sf)
|| fil_space_t::is_flags_equal(sf, tf)) {
mutex_enter(&fil_system.mutex);
table->space->flags = (table->space->flags
& ~FSP_FLAGS_MEM_MASK)
| (tf & FSP_FLAGS_MEM_MASK);
mutex_exit(&fil_system.mutex);
err = DB_SUCCESS;
} else {
err = DB_CORRUPTION;
}
}
} else {
err = DB_SUCCESS;
......
......@@ -507,8 +507,8 @@ bool fil_node_t::read_page0(bool first)
+ page);
if (!fil_space_t::is_valid_flags(flags, space->id)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED
|| (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) {
if (cflags == ULINT_UNDEFINED) {
invalid:
ib::error()
<< "Expected tablespace flags "
<< ib::hex(space->flags)
......@@ -518,9 +518,19 @@ bool fil_node_t::read_page0(bool first)
return false;
}
ulint cf = cflags & ~FSP_FLAGS_MEM_MASK;
ulint sf = space->flags & ~FSP_FLAGS_MEM_MASK;
if (!fil_space_t::is_flags_equal(cf, sf)
&& !fil_space_t::is_flags_equal(sf, cf)) {
goto invalid;
}
flags = cflags;
}
ut_ad(!(flags & FSP_FLAGS_MEM_MASK));
/* Try to read crypt_data from page 0 if it is not yet read. */
if (!space->crypt_data) {
space->crypt_data = fil_space_read_crypt_data(
......@@ -552,10 +562,7 @@ bool fil_node_t::read_page0(bool first)
size_bytes &= ~os_offset_t(mask);
}
if (space->flags != flags
&& fil_space_t::is_flags_equal(flags, space->flags)) {
space->flags = flags;
}
space->flags = (space->flags & FSP_FLAGS_MEM_MASK) | flags;
this->size = ulint(size_bytes / psize);
space->size += this->size;
......@@ -3887,7 +3894,7 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
{
ut_ad(!srv_read_only_mode);
ut_ad(fil_space_t::is_valid_flags(flags, space->id));
if (space->full_crc32()) {
if (space->full_crc32() || fil_space_t::full_crc32(flags)) {
return;
}
if (!space->size && (space->purpose != FIL_TYPE_TABLESPACE
......@@ -3947,7 +3954,11 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&fil_system.mutex);
if (fil_space_t* space = fil_space_get_by_id(id)) {
if ((space->flags ^ expected_flags) & ~FSP_FLAGS_MEM_MASK) {
ulint tf = expected_flags & ~FSP_FLAGS_MEM_MASK;
ulint sf = space->flags & ~FSP_FLAGS_MEM_MASK;
if (!fil_space_t::is_flags_equal(tf, sf)
&& !fil_space_t::is_flags_equal(sf, tf)) {
goto func_exit;
}
......@@ -3963,7 +3974,8 @@ fil_space_for_table_exists_in_mem(
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
FSP_SPACE_FLAGS will not be written back here. */
space->flags = expected_flags;
space->flags = (space->flags & ~FSP_FLAGS_MEM_MASK)
| (expected_flags & FSP_FLAGS_MEM_MASK);
mutex_exit(&fil_system.mutex);
if (!srv_read_only_mode) {
fsp_flags_try_adjust(space, expected_flags
......
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -409,7 +409,8 @@ Datafile::validate_to_dd(ulint space_id, ulint flags)
If the datafile is a file-per-table tablespace then also match
the row format and zip page size. */
if (m_space_id == space_id
&& fil_space_t::is_flags_equal(m_flags, flags)) {
&& (fil_space_t::is_flags_equal(flags, m_flags)
|| fil_space_t::is_flags_equal(m_flags, flags))) {
/* Datafile matches the tablespace expected. */
return(DB_SUCCESS);
}
......
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