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( ...@@ -392,9 +392,21 @@ btr_root_adjust_on_import(
} else { } else {
/* Check that the table flags and the tablespace /* Check that the table flags and the tablespace
flags match. */ flags match. */
err = (dict_tf_to_fsp_flags(table->flags) ulint tf = dict_tf_to_fsp_flags(table->flags);
== table->space->flags) ulint sf = table->space->flags;
? DB_SUCCESS : DB_CORRUPTION; 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 { } else {
err = DB_SUCCESS; err = DB_SUCCESS;
......
...@@ -507,8 +507,8 @@ bool fil_node_t::read_page0(bool first) ...@@ -507,8 +507,8 @@ bool fil_node_t::read_page0(bool first)
+ page); + page);
if (!fil_space_t::is_valid_flags(flags, space->id)) { if (!fil_space_t::is_valid_flags(flags, space->id)) {
ulint cflags = fsp_flags_convert_from_101(flags); ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED if (cflags == ULINT_UNDEFINED) {
|| (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { invalid:
ib::error() ib::error()
<< "Expected tablespace flags " << "Expected tablespace flags "
<< ib::hex(space->flags) << ib::hex(space->flags)
...@@ -518,9 +518,19 @@ bool fil_node_t::read_page0(bool first) ...@@ -518,9 +518,19 @@ bool fil_node_t::read_page0(bool first)
return false; 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; flags = cflags;
} }
ut_ad(!(flags & FSP_FLAGS_MEM_MASK));
/* Try to read crypt_data from page 0 if it is not yet read. */ /* Try to read crypt_data from page 0 if it is not yet read. */
if (!space->crypt_data) { if (!space->crypt_data) {
space->crypt_data = fil_space_read_crypt_data( space->crypt_data = fil_space_read_crypt_data(
...@@ -552,10 +562,7 @@ bool fil_node_t::read_page0(bool first) ...@@ -552,10 +562,7 @@ bool fil_node_t::read_page0(bool first)
size_bytes &= ~os_offset_t(mask); size_bytes &= ~os_offset_t(mask);
} }
if (space->flags != flags space->flags = (space->flags & FSP_FLAGS_MEM_MASK) | flags;
&& fil_space_t::is_flags_equal(flags, space->flags)) {
space->flags = flags;
}
this->size = ulint(size_bytes / psize); this->size = ulint(size_bytes / psize);
space->size += this->size; space->size += this->size;
...@@ -3887,7 +3894,7 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags) ...@@ -3887,7 +3894,7 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
{ {
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(fil_space_t::is_valid_flags(flags, space->id)); 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; return;
} }
if (!space->size && (space->purpose != FIL_TYPE_TABLESPACE if (!space->size && (space->purpose != FIL_TYPE_TABLESPACE
...@@ -3947,7 +3954,11 @@ fil_space_for_table_exists_in_mem( ...@@ -3947,7 +3954,11 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&fil_system.mutex); mutex_enter(&fil_system.mutex);
if (fil_space_t* space = fil_space_get_by_id(id)) { 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; goto func_exit;
} }
...@@ -3963,7 +3974,8 @@ fil_space_for_table_exists_in_mem( ...@@ -3963,7 +3974,8 @@ fil_space_for_table_exists_in_mem(
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK. /* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
FSP_SPACE_FLAGS will not be written back here. */ 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); mutex_exit(&fil_system.mutex);
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
fsp_flags_try_adjust(space, expected_flags fsp_flags_try_adjust(space, expected_flags
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 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) ...@@ -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 If the datafile is a file-per-table tablespace then also match
the row format and zip page size. */ the row format and zip page size. */
if (m_space_id == space_id 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. */ /* Datafile matches the tablespace expected. */
return(DB_SUCCESS); 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