Browse Source

MDEV-11623 MariaDB 10.1 fails to start datadir created with

MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K

The storage format of FSP_SPACE_FLAGS was accidentally broken
already in MariaDB 10.1.0. This fix is bringing the format in
line with other MySQL and MariaDB release series.

Please refer to the comments that were added to fsp0fsp.h
for details.

This is an INCOMPATIBLE CHANGE that affects users of
page_compression and non-default innodb_page_size. Upgrading
to this release will correct the flags in the data files.
If you want to downgrade to earlier MariaDB 10.1.x, please refer
to the test innodb.101_compatibility how to reset the
FSP_SPACE_FLAGS in the files.

NOTE: MariaDB 10.1.0 to 10.1.20 can misinterpret
uncompressed data files with innodb_page_size=4k or 64k as
compressed innodb_page_size=16k files, and then probably fail
when trying to access the pages. See the comments in the
function fsp_flags_convert_from_101() for detailed analysis.

Move PAGE_COMPRESSION to FSP_SPACE_FLAGS bit position 16.
In this way, compressed innodb_page_size=16k tablespaces will not
be mistaken for uncompressed ones by MariaDB 10.1.0 to 10.1.20.

Derive PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES and DATA_DIR from the
dict_table_t::flags when the table is available, in
fil_space_for_table_exists_in_mem() or fil_open_single_table_tablespace().
During crash recovery, fil_load_single_table_tablespace() will use
innodb_compression_level for the PAGE_COMPRESSION_LEVEL.

FSP_FLAGS_MEM_MASK: A bitmap of the memory-only fil_space_t::flags
that are not to be written to FSP_SPACE_FLAGS. Currently, these will
include PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES and DATA_DIR.

Introduce the macro FSP_FLAGS_PAGE_SSIZE(). We only support
one innodb_page_size for the whole instance.

When creating a dummy tablespace for the redo log, use
fil_space_t::flags=0. The flags are never written to the redo log files.

Remove many FSP_FLAGS_SET_ macros.

dict_tf_verify_flags(): Remove. This is basically only duplicating
the logic of dict_tf_to_fsp_flags(), used in a debug assertion.

fil_space_t::mark: Remove. This flag was not used for anything.

fil_space_for_table_exists_in_mem(): Remove the unnecessary parameter
mark_space, and add a parameter for table flags. Check that
fil_space_t::flags match the table flags, and adjust the (memory-only)
flags based on the table flags.

fil_node_open_file(): Remove some redundant or unreachable conditions,
do not use stderr for output, and avoid unnecessary server aborts.

fil_user_tablespace_restore_page(): Convert the flags, so that the
correct page_size will be used when restoring a page from the
doublewrite buffer.

fil_space_get_page_compressed(), fsp_flags_is_page_compressed(): Remove.
It suffices to have fil_space_is_page_compressed().

FSP_FLAGS_WIDTH_DATA_DIR, FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL,
FSP_FLAGS_WIDTH_ATOMIC_WRITES: Remove, because these flags do not
exist in the FSP_SPACE_FLAGS but only in memory.

fsp_flags_try_adjust(): New function, to adjust the FSP_SPACE_FLAGS
in page 0. Called by fil_open_single_table_tablespace(),
fil_space_for_table_exists_in_mem(), innobase_start_or_create_for_mysql()
except if --innodb-read-only is active.

fsp_flags_is_valid(ulint): Reimplement from the scratch, with
accurate comments. Do not display any details of detected
inconsistencies, because the output could be confusing when
dealing with MariaDB 10.1.x data files.

fsp_flags_convert_from_101(ulint): Convert flags from buggy
MariaDB 10.1.x format, or return ULINT_UNDEFINED if the flags
cannot be in MariaDB 10.1.x format.

fsp_flags_match(): Check the flags when probing files.
Implemented based on fsp_flags_is_valid()
and fsp_flags_convert_from_101().

dict_check_tablespaces_and_store_max_id(): Do not access the
page after committing the mini-transaction.

IMPORT TABLESPACE fixes:

AbstractCallback::init(): Convert the flags.

FetchIndexRootPages::operator(): Check that the tablespace flags match the
table flags. Do not attempt to convert tablespace flags to table flags,
because the conversion would necessarily be lossy.

PageConverter::update_header(): Write back the correct flags.
This takes care of the flags in IMPORT TABLESPACE.
pull/287/head
Marko Mäkelä 9 years ago
parent
commit
ab1e6fefd8
  1. 25
      mysql-test/suite/innodb/include/ibd_convert.pl
  2. 48
      mysql-test/suite/innodb/r/101_compatibility.result
  3. 2
      mysql-test/suite/innodb/r/doublewrite.result
  4. 5
      mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result
  5. 101
      mysql-test/suite/innodb/t/101_compatibility.test
  6. 42
      mysql-test/suite/innodb/t/doublewrite.test
  7. 3
      mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test
  8. 15
      storage/innobase/buf/buf0dblwr.cc
  9. 20
      storage/innobase/dict/dict0load.cc
  10. 396
      storage/innobase/fil/fil0fil.cc
  11. 3
      storage/innobase/fsp/fsp0fsp.cc
  12. 40
      storage/innobase/include/dict0dict.ic
  13. 13
      storage/innobase/include/dict0pagecompress.h
  14. 88
      storage/innobase/include/dict0pagecompress.ic
  15. 41
      storage/innobase/include/fil0fil.h
  16. 13
      storage/innobase/include/fil0pagecompress.h
  17. 430
      storage/innobase/include/fsp0fsp.h
  18. 153
      storage/innobase/include/fsp0fsp.ic
  19. 11
      storage/innobase/include/fsp0pagecompress.h
  20. 28
      storage/innobase/include/fsp0pagecompress.ic
  21. 94
      storage/innobase/row/row0import.cc
  22. 11
      storage/innobase/row/row0mysql.cc
  23. 18
      storage/innobase/srv/srv0start.cc
  24. 15
      storage/xtradb/buf/buf0dblwr.cc
  25. 20
      storage/xtradb/dict/dict0load.cc
  26. 395
      storage/xtradb/fil/fil0fil.cc
  27. 3
      storage/xtradb/fsp/fsp0fsp.cc
  28. 40
      storage/xtradb/include/dict0dict.ic
  29. 13
      storage/xtradb/include/dict0pagecompress.h
  30. 88
      storage/xtradb/include/dict0pagecompress.ic
  31. 41
      storage/xtradb/include/fil0fil.h
  32. 13
      storage/xtradb/include/fil0pagecompress.h
  33. 437
      storage/xtradb/include/fsp0fsp.h
  34. 153
      storage/xtradb/include/fsp0fsp.ic
  35. 11
      storage/xtradb/include/fsp0pagecompress.h
  36. 28
      storage/xtradb/include/fsp0pagecompress.ic
  37. 94
      storage/xtradb/row/row0import.cc
  38. 11
      storage/xtradb/row/row0mysql.cc
  39. 18
      storage/xtradb/srv/srv0start.cc

25
mysql-test/suite/innodb/include/ibd_convert.pl

@ -0,0 +1,25 @@
#!/usr/bin/perl
# Convert tablespace flags to the format understood by MariaDB 10.1.0..10.1.20,
# with the assumption that the flags were correct.
sub convert_to_mariadb_101
{
my ($file, $page_size) = @_;
open(FILE, "+<", $file) or die "Unable to open $file\n";
sysread(FILE, $_, $page_size)==$page_size||die "Unable to read $file\n";
sysseek(FILE, 0, 0)||die "Unable to seek $file\n";
# FIL_PAGE_DATA + FSP_SPACE_FLAGS = 38 + 16 = 54 bytes from the start
my($flags) = unpack "x[54]N";
my $badflags = ($flags & 0x3f);
my $compression_level=6;
$badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16);
$badflags |= ($flags & 15 << 6) << 7; # PAGE_SSIZE
substr ($_, 54, 4) = pack("N", $badflags);
# Replace the innodb_checksum_algorithm=none checksum
substr ($_, 0, 4) = pack("N", 0xdeadbeef);
substr ($_, $page_size - 8, 4) = pack("N", 0xdeadbeef);
syswrite(FILE, $_, $page_size)==$page_size||die "Unable to write $file\n";
close(FILE);
}

48
mysql-test/suite/innodb/r/101_compatibility.result

@ -0,0 +1,48 @@
#
# MDEV-11623 MariaDB 10.1 fails to start datadir created with
# MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K
#
call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace");
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_file_format=Barracuda;
CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT;
CREATE TABLE td(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
CREATE TABLE tz(a INT)ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
CREATE TABLE tdd(a INT) ENGINE=InnoDB, DATA DIRECTORY='MYSQL_TMP_DIR';
CREATE TABLE tp(a INT) ENGINE=InnoDB page_compressed=1;
CREATE TABLE ti(a INT) ENGINE=InnoDB;
FLUSH TABLES ti FOR EXPORT;
backup: ti
UNLOCK TABLES;
ALTER TABLE ti DISCARD TABLESPACE;
restore: ti .ibd and .cfg files
ALTER TABLE ti IMPORT TABLESPACE;
BEGIN;
INSERT INTO tr VALUES(1);
INSERT INTO tc VALUES(1);
INSERT INTO td VALUES(1);
INSERT INTO tz VALUES(1);
INSERT INTO tdd VALUES(1);
INSERT INTO tp VALUES(1);
INSERT INTO ti VALUES(1);
# Kill the server
CHECK TABLE tr,tc,td,tz,tdd,tp,ti;
Table Op Msg_type Msg_text
test.tr check status OK
test.tc check status OK
test.td check status OK
test.tz check status OK
test.tdd check status OK
test.tp check status OK
test.ti check status OK
CHECK TABLE tr,tc,td,tz,tdd,tp,ti;
Table Op Msg_type Msg_text
test.tr check status OK
test.tc check status OK
test.td check status OK
test.tz check status OK
test.tdd check status OK
test.tp check status OK
test.ti check status OK
DROP TABLE tr,tc,td,tz,tdd,tp,ti;

2
mysql-test/suite/innodb/r/doublewrite.result

@ -39,6 +39,8 @@ set global innodb_buf_flush_list_now = 1;
# Kill the server
# Make the first page (page_no=0) of the user tablespace
# full of zeroes.
#
# MDEV-11623: Use old FSP_SPACE_FLAGS in the doublewrite buffer.
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK

5
mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result

@ -1,4 +1,5 @@
call mtr.add_suppression("InnoDB: Page for tablespace .* ");
call mtr.add_suppression("InnoDB: Page for tablespace ");
call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS=0x");
FLUSH TABLES;
SET GLOBAL innodb_file_per_table = 1;
SELECT @@innodb_file_per_table;
@ -565,7 +566,7 @@ ERROR HY000: Tablespace has been discarded for table 't1'
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure";
ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table '"test_wl5522"."t1"' : Unsupported
ERROR HY000: Internal error: Cannot reset LSNs in table '"test_wl5522"."t1"' : Data structure corruption
SET SESSION debug_dbug="-d,fsp_flags_is_valid_failure";
DROP TABLE test_wl5522.t1;
unlink: t1.ibd

101
mysql-test/suite/innodb/t/101_compatibility.test

@ -0,0 +1,101 @@
--source include/have_innodb.inc
--source include/not_embedded.inc
-- echo #
-- echo # MDEV-11623 MariaDB 10.1 fails to start datadir created with
-- echo # MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K
-- echo #
# This is actually testing the opposite: starting the fixed 10.1 with
# buggy 10.1 files (by manually converting the flags in the files).
call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace");
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_file_format=Barracuda;
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
let MYSQLD_DATADIR=`select @@datadir`;
CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT;
CREATE TABLE td(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
--disable_warnings
CREATE TABLE tz(a INT)ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
--enable_warnings
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
EVAL CREATE TABLE tdd(a INT) ENGINE=InnoDB, DATA DIRECTORY='$MYSQL_TMP_DIR';
CREATE TABLE tp(a INT) ENGINE=InnoDB page_compressed=1;
CREATE TABLE ti(a INT) ENGINE=InnoDB;
FLUSH TABLES ti FOR EXPORT;
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_backup_tablespaces("test", "ti");
EOF
UNLOCK TABLES;
ALTER TABLE ti DISCARD TABLESPACE;
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_discard_tablespaces("test", "ti");
ib_restore_tablespaces("test", "ti");
do "$ENV{MTR_SUITE_DIR}/include/ibd_convert.pl";
my $ps = $ENV{INNODB_PAGE_SIZE};
my $dd = $ENV{MYSQLD_DATADIR};
convert_to_mariadb_101("$dd/test/ti.ibd", $ps);
EOF
ALTER TABLE ti IMPORT TABLESPACE;
BEGIN;
INSERT INTO tr VALUES(1);
INSERT INTO tc VALUES(1);
INSERT INTO td VALUES(1);
INSERT INTO tz VALUES(1);
INSERT INTO tdd VALUES(1);
INSERT INTO tp VALUES(1);
INSERT INTO ti VALUES(1);
--source include/kill_mysqld.inc
perl;
do "$ENV{MTR_SUITE_DIR}/include/ibd_convert.pl";
my $ps = $ENV{INNODB_PAGE_SIZE};
my $dd = $ENV{MYSQLD_DATADIR};
convert_to_mariadb_101("$dd/ibdata1", $ps);
convert_to_mariadb_101("$dd/test/tr.ibd", $ps);
convert_to_mariadb_101("$dd/test/tc.ibd", $ps);
convert_to_mariadb_101("$dd/test/td.ibd", $ps);
convert_to_mariadb_101("$dd/test/tz.ibd", 1024) if $ps<32768;
convert_to_mariadb_101("$dd/test/tp.ibd", $ps);
convert_to_mariadb_101("$dd/test/ti.ibd", $ps);
convert_to_mariadb_101("$ENV{MYSQL_TMP_DIR}/test/tdd.ibd", $ps);
EOF
--source include/start_mysqld.inc
CHECK TABLE tr,tc,td,tz,tdd,tp,ti;
--source include/shutdown_mysqld.inc
perl;
do "$ENV{MTR_SUITE_DIR}/include/ibd_convert.pl";
my $ps = $ENV{INNODB_PAGE_SIZE};
my $dd = $ENV{MYSQLD_DATADIR};
convert_to_mariadb_101("$dd/ibdata1", $ps);
convert_to_mariadb_101("$dd/test/tr.ibd", $ps);
convert_to_mariadb_101("$dd/test/tc.ibd", $ps);
convert_to_mariadb_101("$dd/test/td.ibd", $ps);
convert_to_mariadb_101("$dd/test/tz.ibd", 1024) if $ps<32768;
convert_to_mariadb_101("$dd/test/tp.ibd", $ps);
convert_to_mariadb_101("$dd/test/ti.ibd", $ps);
convert_to_mariadb_101("$ENV{MYSQL_TMP_DIR}/test/tdd.ibd", $ps);
EOF
--let $restart_parameters=--innodb-read-only
--source include/start_mysqld.inc
CHECK TABLE tr,tc,td,tz,tdd,tp,ti;
--source include/shutdown_mysqld.inc
--let $restart_parameters=
--source include/start_mysqld.inc
DROP TABLE tr,tc,td,tz,tdd,tp,ti;

42
mysql-test/suite/innodb/t/doublewrite.test

@ -17,7 +17,7 @@ call mtr.add_suppression("space header page consists of zero bytes.*test.t1");
call mtr.add_suppression("checksum mismatch in tablespace.*test.t1");
call mtr.add_suppression("Current page size .* != page size on page");
call mtr.add_suppression("innodb-page-size mismatch in tablespace.*test.t1");
call mtr.add_suppression("Database page corruption");
call mtr.add_suppression("Trying to recover page.*from the doublewrite buffer");
--enable_query_log
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
@ -65,14 +65,48 @@ set global innodb_buf_flush_list_now = 1;
--echo # Make the first page (page_no=0) of the user tablespace
--echo # full of zeroes.
--echo #
--echo # MDEV-11623: Use old FSP_SPACE_FLAGS in the doublewrite buffer.
perl;
use IO::Handle;
my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd";
my $page_size = $ENV{INNODB_PAGE_SIZE};
my $page;
open(FILE, "+<", $fname) or die;
FILE->autoflush(1);
binmode FILE;
print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'});
sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $file\n";
sysseek(FILE, 0, 0)||die "Unable to seek $file\n";
die unless syswrite(FILE, chr(0) x $page_size, $page_size) == $page_size;
close FILE;
open(FILE, "+<", "$ENV{MYSQLD_DATADIR}ibdata1")||die "cannot open ibdata1\n";
sysseek(FILE, 6 * $page_size - 190, 0)||die "Unable to seek ibdata1\n";
sysread(FILE, $_, 12) == 12||die "Unable to read TRX_SYS\n";
my($magic,$d1,$d2)=unpack "NNN";
die "magic=$magic, $d1, $d2\n" unless $magic == 536853855 && $d2 >= $d1 + 64;
sysseek(FILE, $d1 * $page_size, 0)||die "Unable to seek ibdata1\n";
# Find the page in the doublewrite buffer
for (my $d = $d1; $d < $d2 + 64; $d++)
{
sysread(FILE, $_, $page_size)==$page_size||die "Cannot read doublewrite\n";
next unless $_ eq $page;
sysseek(FILE, $d * $page_size, 0)||die "Unable to seek ibdata1\n";
# Write buggy MariaDB 10.1.x FSP_SPACE_FLAGS to the doublewrite buffer
my($flags) = unpack "x[54]N";
my $badflags = ($flags & 0x3f);
my $compression_level=6;
$badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16);
$badflags |= ($flags & 15 << 6) << 7; # PAGE_SSIZE
substr ($_, 54, 4) = pack("N", $badflags);
# Replace the innodb_checksum_algorithm=none checksum
substr ($_, 0, 4) = pack("N", 0xdeadbeef);
substr ($_, $page_size - 8, 4) = pack("N", 0xdeadbeef);
syswrite(FILE, $_, $page_size)==$page_size||die "Unable to write $file\n";
close(FILE);
exit 0;
}
die "Did not find the page in the doublewrite buffer ($d1,$d2)\n";
EOF
--source include/start_mysqld.inc

3
mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test

@ -17,7 +17,8 @@
# allow test to run only when innodb-page-size=16
--source include/have_innodb_16k.inc
call mtr.add_suppression("InnoDB: Page for tablespace .* ");
call mtr.add_suppression("InnoDB: Page for tablespace ");
call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS=0x");
FLUSH TABLES;
let MYSQLD_DATADIR =`SELECT @@datadir`;

15
storage/innobase/buf/buf0dblwr.cc

@ -589,6 +589,21 @@ buf_dblwr_process()
continue;
}
if (page_no == 0) {
/* Check the FSP_SPACE_FLAGS. */
ulint flags = fsp_header_get_flags(page);
if (!fsp_flags_is_valid(flags)
&& fsp_flags_convert_from_101(flags)
== ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_WARN,
"Ignoring a doublewrite copy of page "
ULINTPF ":0 due to invalid flags 0x%x",
space_id, int(flags));
continue;
}
/* The flags on the page should be converted later. */
}
/* Write the good page from the doublewrite buffer to
the intended position. */

20
storage/innobase/dict/dict0load.cc

@ -1052,8 +1052,6 @@ loop:
btr_pcur_store_position(&pcur, &mtr);
mtr_commit(&mtr);
/* For tables created with old versions of InnoDB,
SYS_TABLES.MIX_LEN may contain garbage. Such tables
would always be in ROW_FORMAT=REDUNDANT. Pretend that
@ -1087,16 +1085,19 @@ loop:
if (space_id == 0) {
/* The system tablespace always exists. */
ut_ad(!discarded);
goto next_tablespace;
mem_free(name);
goto loop;
}
mtr_commit(&mtr);
switch (dict_check) {
case DICT_CHECK_ALL_LOADED:
/* All tablespaces should have been found in
fil_load_single_table_tablespaces(). */
if (fil_space_for_table_exists_in_mem(
space_id, name, TRUE, !(is_temp || discarded),
false, NULL, 0)
space_id, name, !(is_temp || discarded),
false, NULL, 0, flags)
&& !(is_temp || discarded)) {
/* If user changes the path of .ibd files in
*.isl files before doing crash recovery ,
@ -1128,8 +1129,8 @@ loop:
/* Some tablespaces may have been opened in
trx_resurrect_table_locks(). */
if (fil_space_for_table_exists_in_mem(
space_id, name, FALSE, FALSE,
false, NULL, 0)) {
space_id, name, false,
false, NULL, 0, flags)) {
break;
}
/* fall through */
@ -1191,7 +1192,6 @@ loop:
max_space_id = space_id;
}
next_tablespace:
mem_free(name);
mtr_start(&mtr);
@ -2382,8 +2382,8 @@ err_exit:
table->ibd_file_missing = TRUE;
} else if (!fil_space_for_table_exists_in_mem(
table->space, name, FALSE, FALSE, true, heap,
table->id)) {
table->space, name, false, true, heap,
table->id, table->flags)) {
if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
/* Do not bother to retry opening temporary tables. */

396
storage/innobase/fil/fil0fil.cc

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@ -596,10 +596,7 @@ fil_node_open_file(
ibool success;
byte* buf2;
byte* page;
ulint space_id;
ulint flags=0;
ulint page_size;
ulint atomic_writes=0;
ut_ad(mutex_own(&(system->mutex)));
ut_a(node->n_pending == 0);
@ -621,8 +618,6 @@ fil_node_open_file(
/* The following call prints an error message */
os_file_get_last_error(true);
ut_print_timestamp(stderr);
ib_logf(IB_LOG_LEVEL_WARN, "InnoDB: Error: cannot "
"open %s\n. InnoDB: Have you deleted .ibd "
"files under a running mysqld server?\n",
@ -648,17 +643,13 @@ fil_node_open_file(
ut_a(fil_is_user_tablespace_id(space->id));
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Error: the size of single-table"
" tablespace file %s\n"
"InnoDB: is only " UINT64PF ","
" should be at least %lu!\n",
node->name,
size_bytes,
(ulong) (FIL_IBD_FILE_INITIAL_SIZE
* UNIV_PAGE_SIZE));
ut_a(0);
ib_logf(IB_LOG_LEVEL_ERROR,
"The size of the file %s is only " UINT64PF
" bytes, should be at least " ULINTPF,
node->name, size_bytes,
FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE);
os_file_close(node->handle);
return(false);
}
/* Read the first page of the tablespace */
@ -671,78 +662,34 @@ fil_node_open_file(
success = os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE);
srv_stats.page0_read.add(1);
space_id = fsp_header_get_space_id(page);
flags = fsp_header_get_flags(page);
page_size = fsp_flags_get_page_size(flags);
atomic_writes = fsp_flags_get_atomic_writes(flags);
const ulint space_id = fsp_header_get_space_id(page);
ulint flags = fsp_header_get_flags(page);
ut_free(buf2);
/* Close the file now that we have read the space id from it */
os_file_close(node->handle);
if (UNIV_UNLIKELY(space_id != space->id)) {
fprintf(stderr,
"InnoDB: Error: tablespace id is %lu"
" in the data dictionary\n"
"InnoDB: but in file %s it is %lu!\n",
space->id, node->name, space_id);
ut_error;
}
if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
|| space_id == 0)) {
fprintf(stderr,
"InnoDB: Error: tablespace id %lu"
" in file %s is not sensible\n",
(ulong) space_id, node->name);
ut_error;
}
if (UNIV_UNLIKELY(fsp_flags_get_page_size(space->flags)
!= page_size)) {
fprintf(stderr,
"InnoDB: Error: tablespace file %s"
" has page size 0x%lx\n"
"InnoDB: but the data dictionary"
" expects page size 0x%lx!\n",
node->name, flags,
fsp_flags_get_page_size(space->flags));
if (!fsp_flags_is_valid(flags)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Expected tablespace flags 0x%x"
" but found 0x%x in the file %s",
int(space->flags), int(flags),
node->name);
return(false);
}
ut_error;
flags = cflags;
}
if (UNIV_UNLIKELY(space->flags != flags)) {
ulint sflags = (space->flags & ~FSP_FLAGS_MASK_DATA_DIR);
ulint fflags = (flags & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
/* DATA_DIR option is on different place on MariaDB
compared to MySQL. If this is the difference. Fix
it. */
if (sflags == fflags) {
fprintf(stderr,
"InnoDB: Warning: Table flags 0x%lx"
" in the data dictionary but in file %s are 0x%lx!\n"
" Temporally corrected because DATA_DIR option to 0x%lx.\n",
space->flags, node->name, flags, space->flags);
flags = space->flags;
}
page_size = fsp_flags_get_page_size(flags);
if (!dict_tf_verify_flags(space->flags, flags)) {
fprintf(stderr,
"InnoDB: Error: table flags are 0x%lx"
" in the data dictionary\n"
"InnoDB: but the flags in file %s are 0x%lx!\n",
space->flags, node->name, flags);
ut_error;
}
if (UNIV_UNLIKELY(space_id != space->id)) {
ib_logf(IB_LOG_LEVEL_ERROR,
"tablespace id is " ULINTPF " in the data dictionary"
" but in file %s it is " ULINTPF "!\n",
space->id, node->name, space_id);
return(false);
}
if (size_bytes >= (1024*1024)) {
@ -764,7 +711,7 @@ add_size:
space->size += node->size;
}
atomic_writes = fsp_flags_get_atomic_writes(space->flags);
ulint atomic_writes = fsp_flags_get_atomic_writes(space->flags);
/* printf("Opening file %s\n", node->name); */
@ -1534,7 +1481,6 @@ fil_space_create(
fil_system->tablespace_version++;
space->tablespace_version = fil_system->tablespace_version;
space->mark = FALSE;
if (purpose == FIL_TABLESPACE && !recv_recovery_on
&& id > fil_system->max_assigned_id) {
@ -2273,27 +2219,21 @@ fil_write_flushed_lsn_to_data_files(
return(DB_SUCCESS);
}
/*******************************************************************//**
Checks the consistency of the first data page of a tablespace
/** Check the consistency of the first data page of a tablespace
at database startup.
@param[in] page page frame
@param[in] space_id tablespace identifier
@param[in] flags tablespace flags
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
static MY_ATTRIBUTE((warn_unused_result))
const char*
fil_check_first_page(
/*=================*/
const page_t* page) /*!< in: data page */
fil_check_first_page(const page_t* page, ulint space_id, ulint flags)
{
ulint space_id;
ulint flags;
if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) {
return(NULL);
}
space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page);
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
if (UNIV_PAGE_SIZE != fsp_flags_get_page_size(flags)) {
fprintf(stderr,
"InnoDB: Error: Current page size %lu != "
@ -2342,7 +2282,7 @@ fil_read_first_page(
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
ulint* flags, /*!< out: FSP_SPACE_FLAGS */
ulint* space_id, /*!< out: tablespace ID */
#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< out: min of archived
@ -2378,12 +2318,22 @@ fil_read_first_page(
*flags and *space_id as they were read from the first file and
do not validate the first page. */
if (!one_read_already) {
*flags = fsp_header_get_flags(page);
*space_id = fsp_header_get_space_id(page);
}
*flags = fsp_header_get_flags(page);
if (!one_read_already) {
check_msg = fil_check_first_page(page);
if (!fsp_flags_is_valid(*flags)) {
ulint cflags = fsp_flags_convert_from_101(*flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Invalid flags 0x%x in tablespace %u",
unsigned(*flags), unsigned(*space_id));
return "invalid tablespace flags";
} else {
*flags = cflags;
}
}
check_msg = fil_check_first_page(page, *space_id, *flags);
}
flushed_lsn = mach_read_from_8(page +
@ -2577,6 +2527,7 @@ fil_op_write_log(
ulint len;
log_ptr = mlog_open(mtr, 11 + 2 + 1);
ut_ad(fsp_flags_is_valid(flags));
if (!log_ptr) {
/* Logging in mtr is switched off during crash recovery:
@ -3783,7 +3734,7 @@ fil_create_new_single_table_tablespace(
ibool success;
/* TRUE if a table is created with CREATE TEMPORARY TABLE */
bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY);
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags);
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0;
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
fil_space_crypt_t *crypt_data = NULL;
@ -3791,7 +3742,7 @@ fil_create_new_single_table_tablespace(
ut_ad(!srv_read_only_mode);
ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
ut_a(fsp_flags_is_valid(flags));
ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK));
if (is_temp) {
/* Temporary table filepath */
@ -3884,12 +3835,9 @@ fil_create_new_single_table_tablespace(
memset(page, '\0', UNIV_PAGE_SIZE);
/* Add the UNIV_PAGE_SIZE to the table flags and write them to the
tablespace header. */
flags = fsp_flags_set_page_size(flags, UNIV_PAGE_SIZE);
flags |= FSP_FLAGS_PAGE_SSIZE();
fsp_header_init_fields(page, space_id, flags);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
ut_ad(fsp_flags_is_valid(flags));
if (!(fsp_flags_is_compressed(flags))) {
buf_flush_init_for_writing(page, NULL, 0);
@ -3968,7 +3916,8 @@ fil_create_new_single_table_tablespace(
fil_op_write_log(flags
? MLOG_FILE_CREATE2
: MLOG_FILE_CREATE,
space_id, mlog_file_flag, flags,
space_id, mlog_file_flag,
flags & ~FSP_FLAGS_MEM_MASK,
tablename, NULL, &mtr);
mtr_commit(&mtr);
@ -4032,6 +3981,39 @@ fil_report_bad_tablespace(
(ulong) expected_id, (ulong) expected_flags);
}
/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations.
(Typically when upgrading from MariaDB 10.1.0..10.1.20.)
@param[in] space_id tablespace ID
@param[in] flags desired tablespace flags */
UNIV_INTERN
void
fsp_flags_try_adjust(ulint space_id, ulint flags)
{
ut_ad(!srv_read_only_mode);
ut_ad(fsp_flags_is_valid(flags));
mtr_t mtr;
mtr_start(&mtr);
if (buf_block_t* b = buf_page_get(
space_id, fsp_flags_get_zip_size(flags), 0, RW_X_LATCH,
&mtr)) {
ulint f = fsp_header_get_flags(b->frame);
/* Suppress the message if only the DATA_DIR flag to differs. */
if ((f ^ flags) & ~(1U << FSP_FLAGS_POS_RESERVED)) {
ib_logf(IB_LOG_LEVEL_WARN,
"adjusting FSP_SPACE_FLAGS of tablespace "
ULINTPF " from 0x%x to 0x%x",
space_id, int(f), int(flags));
}
if (f != flags) {
mlog_write_ulint(FSP_HEADER_OFFSET
+ FSP_SPACE_FLAGS + b->frame,
flags, MLOG_4BYTES, &mtr);
}
}
mtr_commit(&mtr);
}
/********************************************************************//**
Tries to open a single-table tablespace and optionally checks that the
space id in it is correct. If this does not succeed, print an error message
@ -4061,7 +4043,7 @@ fil_open_single_table_tablespace(
bool validate, /*!< in: Do we validate tablespace? */
bool fix_dict, /*!< in: Can we fix the dictionary? */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
ulint flags, /*!< in: expected FSP_SPACE_FLAGS */
const char* tablename, /*!< in: table name in the
databasename/tablename format */
const char* path_in, /*!< in: tablespace filepath */
@ -4086,20 +4068,13 @@ fil_open_single_table_tablespace(
/* Table flags can be ULINT_UNDEFINED if
dict_tf_to_fsp_flags_failure is set. */
if (flags != ULINT_UNDEFINED) {
if (!fsp_flags_is_valid(flags)) {
return(DB_CORRUPTION);
}
} else {
if (flags == ULINT_UNDEFINED) {
return(DB_CORRUPTION);
}
ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK));
atomic_writes = fsp_flags_get_atomic_writes(flags);
/* If the tablespace was relocated, we do not
compare the DATA_DIR flag */
ulint mod_flags = flags & ~FSP_FLAGS_MASK_DATA_DIR;
memset(&def, 0, sizeof(def));
memset(&dict, 0, sizeof(dict));
memset(&remote, 0, sizeof(remote));
@ -4180,31 +4155,17 @@ fil_open_single_table_tablespace(
&space_arch_log_no, &space_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
&def.lsn, &def.lsn, &def.crypt_data);
def.valid = !def.check_msg;
if (table) {
table->crypt_data = def.crypt_data;
table->page_0_read = true;
}
/* Validate this single-table-tablespace with SYS_TABLES,
but do not compare the DATA_DIR flag, in case the
tablespace was relocated. */
ulint newf = def.flags;
if (newf != mod_flags) {
if (FSP_FLAGS_HAS_DATA_DIR(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR);
} else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
}
}
if (def.valid && def.id == id
&& newf == mod_flags) {
def.valid = !def.check_msg && def.id == id
&& fsp_flags_match(flags, def.flags);
if (def.valid) {
valid_tablespaces_found++;
} else {
def.valid = false;
/* Do not use this tablespace. */
fil_report_bad_tablespace(
def.filepath, def.check_msg, def.id,
@ -4220,30 +4181,18 @@ fil_open_single_table_tablespace(
&remote.arch_log_no, &remote.arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
&remote.lsn, &remote.lsn, &remote.crypt_data);
remote.valid = !remote.check_msg;
if (table) {
table->crypt_data = remote.crypt_data;
table->page_0_read = true;
}
/* Validate this single-table-tablespace with SYS_TABLES,
but do not compare the DATA_DIR flag, in case the
tablespace was relocated. */
ulint newf = remote.flags;
if (newf != mod_flags) {
if (FSP_FLAGS_HAS_DATA_DIR(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR);
} else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
}
}
if (remote.valid && remote.id == id
&& newf == mod_flags) {
/* Validate this single-table-tablespace with SYS_TABLES. */
remote.valid = !remote.check_msg && remote.id == id
&& fsp_flags_match(flags, remote.flags);
if (remote.valid) {
valid_tablespaces_found++;
} else {
remote.valid = false;
/* Do not use this linked tablespace. */
fil_report_bad_tablespace(
remote.filepath, remote.check_msg, remote.id,
@ -4260,30 +4209,19 @@ fil_open_single_table_tablespace(
&dict.arch_log_no, &dict.arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
&dict.lsn, &dict.lsn, &dict.crypt_data);
dict.valid = !dict.check_msg;
if (table) {
table->crypt_data = dict.crypt_data;
table->page_0_read = true;
}
/* Validate this single-table-tablespace with SYS_TABLES,
but do not compare the DATA_DIR flag, in case the
tablespace was relocated. */
ulint newf = dict.flags;
if (newf != mod_flags) {
if (FSP_FLAGS_HAS_DATA_DIR(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR);
} else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
}
}
/* Validate this single-table-tablespace with SYS_TABLES. */
dict.valid = !dict.check_msg && dict.id == id
&& fsp_flags_match(flags, dict.flags);
if (dict.valid && dict.id == id
&& newf == mod_flags) {
if (dict.valid) {
valid_tablespaces_found++;
} else {
dict.valid = false;
/* Do not use this tablespace. */
fil_report_bad_tablespace(
dict.filepath, dict.check_msg, dict.id,
@ -4481,6 +4419,10 @@ cleanup_and_exit:
mem_free(def.filepath);
if (err == DB_SUCCESS && !srv_read_only_mode) {
fsp_flags_try_adjust(id, flags & ~FSP_FLAGS_MEM_MASK);
}
return(err);
}
#endif /* !UNIV_HOTBACKUP */
@ -4662,7 +4604,23 @@ fil_user_tablespace_restore_page(
goto out;
}
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
if (!fsp_flags_is_valid(flags)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_WARN,
"Ignoring a doublewrite copy of page "
ULINTPF ":" ULINTPF
" due to invalid flags 0x%x",
fsp->id, page_no, int(flags));
err = false;
goto out;
}
flags = cflags;
/* The flags on the page should be converted later. */
}
zip_size = fsp_flags_get_zip_size(flags);
page_size = fsp_flags_get_page_size(flags);
@ -5051,6 +5009,16 @@ will_not_choose:
}
mutex_exit(&fil_system->mutex);
#endif /* UNIV_HOTBACKUP */
/* Adjust the memory-based flags that would normally be set by
dict_tf_to_fsp_flags(). In recovery, we have no data dictionary. */
if (FSP_FLAGS_HAS_PAGE_COMPRESSION(fsp->flags)) {
fsp->flags |= page_zip_level
<< FSP_FLAGS_MEM_COMPRESSION_LEVEL;
}
remote.flags |= 1U << FSP_FLAGS_MEM_DATA_DIR;
/* We will leave atomic_writes at ATOMIC_WRITES_DEFAULT.
That will be adjusted in fil_space_for_table_exists_in_mem(). */
ibool file_space_create_success = fil_space_create(
tablename, fsp->id, fsp->flags, FIL_TABLESPACE,
fsp->crypt_data, false);
@ -5342,13 +5310,12 @@ fil_report_missing_tablespace(
name, space_id);
}
/*******************************************************************//**
Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory
/** Check if a matching tablespace exists in the InnoDB tablespace memory
cache. Note that if we have not done a crash recovery at the database startup,
there may be many tablespaces which are not yet in the memory cache.
@return TRUE if a matching tablespace exists in the memory cache */
@return whether a matching tablespace exists in the memory cache */
UNIV_INTERN
ibool
bool
fil_space_for_table_exists_in_mem(
/*==============================*/
ulint id, /*!< in: space id */
@ -5356,13 +5323,7 @@ fil_space_for_table_exists_in_mem(
fil_space_create(). Either the
standard 'dbname/tablename' format
or table->dir_path_of_temp_table */
ibool mark_space, /*!< in: in crash recovery, at database
startup we mark all spaces which have
an associated table in the InnoDB
data dictionary, so that
we can print a warning about orphaned
tablespaces */
ibool print_error_if_does_not_exist,
bool print_error_if_does_not_exist,
/*!< in: print detailed error
information to the .err log if a
matching tablespace is not found from
@ -5370,12 +5331,13 @@ fil_space_for_table_exists_in_mem(
bool adjust_space, /*!< in: whether to adjust space id
when find table space mismatch */
mem_heap_t* heap, /*!< in: heap memory */
table_id_t table_id) /*!< in: table id */
table_id_t table_id, /*!< in: table id */
ulint table_flags) /*!< in: table flags */
{
fil_space_t* fnamespace;
fil_space_t* space;
ut_ad(fil_system);
const ulint expected_flags = dict_tf_to_fsp_flags(table_flags);
mutex_enter(&fil_system->mutex);
@ -5387,42 +5349,31 @@ fil_space_for_table_exists_in_mem(
directory path from the datadir to the file */
fnamespace = fil_space_get_by_name(name);
if (space && space == fnamespace) {
/* Found */
if (mark_space) {
space->mark = TRUE;
}
mutex_exit(&fil_system->mutex);
return(TRUE);
}
/* Info from "fnamespace" comes from the ibd file itself, it can
be different from data obtained from System tables since it is
not transactional. If adjust_space is set, and the mismatching
space are between a user table and its temp table, we shall
adjust the ibd file name according to system table info */
if (adjust_space
&& space != NULL
&& row_is_mysql_tmp_table_name(space->name)
&& !row_is_mysql_tmp_table_name(name)) {
bool valid = space && !((space->flags ^ expected_flags)
& ~FSP_FLAGS_MEM_MASK);
if (!space) {
} else if (!valid || space == fnamespace) {
/* Found with the same file name, or got a flag mismatch. */
goto func_exit;
} else if (adjust_space
&& row_is_mysql_tmp_table_name(space->name)
&& !row_is_mysql_tmp_table_name(name)) {
/* Info from fnamespace comes from the ibd file
itself, it can be different from data obtained from
System tables since renaming files is not
transactional. We shall adjust the ibd file name
according to system table info. */
mutex_exit(&fil_system->mutex);
DBUG_EXECUTE_IF("ib_crash_before_adjust_fil_space",
DBUG_SUICIDE(););
if (fnamespace) {
char* tmp_name;
char* tmp_name = dict_mem_create_temporary_tablename(
heap, name, table_id);
tmp_name = dict_mem_create_temporary_tablename(
heap, name, table_id);
fil_rename_tablespace(fnamespace->name, fnamespace->id,
tmp_name, NULL);
}
fil_rename_tablespace(fnamespace->name, fnamespace->id,
tmp_name, NULL);
DBUG_EXECUTE_IF("ib_crash_after_adjust_one_fil_space",
DBUG_SUICIDE(););
@ -5435,16 +5386,12 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&fil_system->mutex);
fnamespace = fil_space_get_by_name(name);
ut_ad(space == fnamespace);
mutex_exit(&fil_system->mutex);
return(TRUE);
goto func_exit;
}
if (!print_error_if_does_not_exist) {
mutex_exit(&fil_system->mutex);
return(FALSE);
valid = false;
goto func_exit;
}
if (space == NULL) {
@ -5471,10 +5418,8 @@ error_exit:
fputs("InnoDB: Please refer to\n"
"InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
"InnoDB: for how to resolve the issue.\n", stderr);
mutex_exit(&fil_system->mutex);
return(FALSE);
valid = false;
goto func_exit;
}
if (0 != strcmp(space->name, name)) {
@ -5501,9 +5446,19 @@ error_exit:
goto error_exit;
}
func_exit:
if (valid) {
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
FSP_SPACE_FLAGS will not be written back here. */
space->flags = expected_flags;
}
mutex_exit(&fil_system->mutex);
return(FALSE);
if (valid && !srv_read_only_mode) {
fsp_flags_try_adjust(id, expected_flags & ~FSP_FLAGS_MEM_MASK);
}
return(valid);
}
/*******************************************************************//**
@ -7331,9 +7286,8 @@ fil_space_get_crypt_data(
byte *page = static_cast<byte*>(ut_align(buf, UNIV_PAGE_SIZE));
fil_read(true, space_id, 0, 0, 0, UNIV_PAGE_SIZE, page,
NULL, NULL);
ulint flags = fsp_header_get_flags(page);
ulint offset = fsp_header_get_crypt_offset(
fsp_flags_get_zip_size(flags), NULL);
fsp_header_get_zip_size(page), NULL);
space->crypt_data = fil_space_read_crypt_data(space_id, page, offset);
ut_free(buf);

3
storage/innobase/fsp/fsp0fsp.cc

@ -660,6 +660,7 @@ fsp_header_init_fields(
ulint space_id, /*!< in: space id */
ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */
{
flags &= ~FSP_FLAGS_MEM_MASK;
ut_a(fsp_flags_is_valid(flags));
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page,
@ -710,7 +711,7 @@ fsp_header_init(
mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_SPACE_FLAGS, flags,
mlog_write_ulint(header + FSP_SPACE_FLAGS, flags & ~FSP_FLAGS_MEM_MASK,
MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);

40
storage/innobase/include/dict0dict.ic

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates
Copyright (c) 2013, 2016, MariaDB Corporation
Copyright (c) 2013, 2017, 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
@ -914,10 +914,13 @@ dict_tf_to_fsp_flags(
ulint table_flags) /*!< in: dict_table_t::flags */
{
ulint fsp_flags;
ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(
table_flags);
ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags);
ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0)
== (page_compression_level == 0));
DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure",
return(ULINT_UNDEFINED););
@ -925,30 +928,23 @@ dict_tf_to_fsp_flags(
fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0;
/* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */
fsp_flags |= table_flags & DICT_TF_MASK_ZIP_SSIZE;
fsp_flags |= table_flags & DICT_TF_MASK_ATOMIC_BLOBS;
/* In addition, tablespace flags also contain the page size. */
fsp_flags |= fsp_flags_set_page_size(fsp_flags, UNIV_PAGE_SIZE);
fsp_flags |= table_flags
& (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS);
/* The DATA_DIR flag is in a different position in fsp_flag */
fsp_flags |= DICT_TF_HAS_DATA_DIR(table_flags)
? FSP_FLAGS_MASK_DATA_DIR : 0;
fsp_flags |= FSP_FLAGS_PAGE_SSIZE();
/* In addition, tablespace flags also contain if the page
compression is used for this table. */
fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION(fsp_flags, page_compression);
if (page_compression_level) {
fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION;
}
/* In addition, tablespace flags also contain page compression level
if page compression is used for this table. */
fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(fsp_flags, page_compression_level);
ut_a(fsp_flags_is_valid(fsp_flags));
/* In addition, tablespace flags also contain flag if atomic writes
is used for this table */
fsp_flags |= FSP_FLAGS_SET_ATOMIC_WRITES(fsp_flags, atomic_writes);
if (DICT_TF_HAS_DATA_DIR(table_flags)) {
fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR;
}
ut_a(fsp_flags_is_valid(fsp_flags));
ut_a(dict_tf_verify_flags(table_flags, fsp_flags));
fsp_flags |= atomic_writes << FSP_FLAGS_MEM_ATOMIC_WRITES;
fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL;
return(fsp_flags);
}

13
storage/innobase/include/dict0pagecompress.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013 SkySQL Ab. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -56,17 +56,6 @@ dict_table_page_compression_level(
const dict_table_t* table) /*!< in: table */
__attribute__((const));
/********************************************************************//**
Verify that dictionary flags match tablespace flags
@return true if flags match, false if not */
UNIV_INLINE
ibool
dict_tf_verify_flags(
/*=================*/
ulint table_flags, /*!< in: dict_table_t::flags */
ulint fsp_flags) /*!< in: fil_space_t::flags */
__attribute__((const));
/********************************************************************//**
Extract the atomic writes flag from table flags.
@return true if atomic writes are used, false if not used */

88
storage/innobase/include/dict0pagecompress.ic

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013 SkySQL Ab. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -24,92 +24,6 @@ page compression and atomic writes information to dictionary.
Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
***********************************************************************/
/********************************************************************//**
Verify that dictionary flags match tablespace flags
@return true if flags match, false if not */
UNIV_INLINE
ibool
dict_tf_verify_flags(
/*=================*/
ulint table_flags, /*!< in: dict_table_t::flags */
ulint fsp_flags) /*!< in: fil_space_t::flags */
{
ulint table_unused = DICT_TF_GET_UNUSED(table_flags);
ulint compact = DICT_TF_GET_COMPACT(table_flags);
ulint ssize = DICT_TF_GET_ZIP_SSIZE(table_flags);
ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(table_flags);
ulint data_dir = DICT_TF_HAS_DATA_DIR(table_flags);
ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags);
ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags);
ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(fsp_flags);
ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags);
ulint fsp_atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(fsp_flags);
ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags);
ulint fsp_unused = FSP_FLAGS_GET_UNUSED(fsp_flags);
ulint fsp_page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags);
ulint fsp_page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags);
ulint fsp_atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(fsp_flags);
DBUG_EXECUTE_IF("dict_tf_verify_flags_failure",
return(ULINT_UNDEFINED););
ut_a(!table_unused);
ut_a(!fsp_unused);
ut_a(page_ssize == 0 || page_ssize != 0); /* silence compiler */
ut_a(compact == 0 || compact == 1); /* silence compiler */
ut_a(data_dir == 0 || data_dir == 1); /* silence compiler */
ut_a(post_antelope == 0 || post_antelope == 1); /* silence compiler */
if (ssize != zip_ssize) {
fprintf(stderr,
"InnoDB: Error: table flags has zip_ssize %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has zip_ssize %ld\n",
ssize, zip_ssize);
return (FALSE);
}
if (atomic_blobs != fsp_atomic_blobs) {
fprintf(stderr,
"InnoDB: Error: table flags has atomic_blobs %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has atomic_blobs %ld\n",
atomic_blobs, fsp_atomic_blobs);
return (FALSE);
}
if (page_compression != fsp_page_compression) {
fprintf(stderr,
"InnoDB: Error: table flags has page_compression %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file ahas page_compression %ld\n",
page_compression, fsp_page_compression);
return (FALSE);
}
if (page_compression_level != fsp_page_compression_level) {
fprintf(stderr,
"InnoDB: Error: table flags has page_compression_level %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has page_compression_level %ld\n",
page_compression_level, fsp_page_compression_level);
return (FALSE);
}
if (atomic_writes != fsp_atomic_writes) {
fprintf(stderr,
"InnoDB: Error: table flags has atomic writes %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has atomic_writes %ld\n",
atomic_writes, fsp_atomic_writes);
return (FALSE);
}
return(TRUE);
}
/********************************************************************//**
Extract the page compression level from dict_table_t::flags.
These flags are in memory, so assert that they are valid.

41
storage/innobase/include/fil0fil.h

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@ -44,7 +44,6 @@ Created 10/25/1995 Heikki Tuuri
// Forward declaration
struct trx_t;
struct fil_space_t;
typedef std::list<const char*> space_name_list_t;
@ -271,10 +270,6 @@ struct fil_space_t {
an insert buffer merge request for a
page because it actually was for the
previous incarnation of the space */
ibool mark; /*!< this is set to TRUE at database startup if
the space corresponds to a table in the InnoDB
data dictionary; so we can print a warning of
orphaned tablespaces */
ibool stop_ios;/*!< TRUE if we want to rename the
.ibd file of tablespace and want to
stop temporarily posting of new i/o
@ -303,7 +298,8 @@ struct fil_space_t {
/*!< recovered tablespace size in pages;
0 if no size change was read from the redo log,
or if the size change was implemented */
ulint flags; /*!< tablespace flags; see
ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
see fsp0fsp.h,
fsp_flags_is_valid(),
fsp_flags_get_zip_size() */
ulint n_reserved_extents;
@ -455,6 +451,7 @@ fil_node_create(
ibool is_raw) /*!< in: TRUE if a raw device or
a raw disk partition */
MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_LOG_ARCHIVE
/****************************************************************//**
Drops files from the start of a file space, so that its size is cut by
@ -618,7 +615,7 @@ fil_read_first_page(
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
ulint* flags, /*!< out: FSP_SPACE_FLAGS */
ulint* space_id, /*!< out: tablespace ID */
#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< out: min of archived
@ -836,6 +833,14 @@ fil_create_new_single_table_tablespace(
ulint key_id) /*!< in: encryption key_id */
__attribute__((nonnull, warn_unused_result));
#ifndef UNIV_HOTBACKUP
/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations.
(Typically when upgrading from MariaDB 10.1.0..10.1.20.)
@param[in] space_id tablespace ID
@param[in] flags desired tablespace flags */
UNIV_INTERN
void
fsp_flags_try_adjust(ulint space_id, ulint flags);
/********************************************************************//**
Tries to open a single-table tablespace and optionally checks the space id is
right in it. If does not succeed, prints an error message to the .err log. This
@ -864,7 +869,7 @@ fil_open_single_table_tablespace(
bool validate, /*!< in: Do we validate tablespace? */
bool fix_dict, /*!< in: Can we fix the dictionary? */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
ulint flags, /*!< in: expected FSP_SPACE_FLAGS */
const char* tablename, /*!< in: table name in the
databasename/tablename format */
const char* filepath, /*!< in: tablespace filepath */
@ -905,25 +910,18 @@ fil_tablespace_exists_in_mem(
/*=========================*/
ulint id); /*!< in: space id */
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory
/** Check if a matching tablespace exists in the InnoDB tablespace memory
cache. Note that if we have not done a crash recovery at the database startup,
there may be many tablespaces which are not yet in the memory cache.
@return TRUE if a matching tablespace exists in the memory cache */
@return whether a matching tablespace exists in the memory cache */
UNIV_INTERN
ibool
bool
fil_space_for_table_exists_in_mem(
/*==============================*/
ulint id, /*!< in: space id */
const char* name, /*!< in: table name in the standard
'databasename/tablename' format */
ibool mark_space, /*!< in: in crash recovery, at database
startup we mark all spaces which have
an associated table in the InnoDB
data dictionary, so that
we can print a warning about orphaned
tablespaces */
ibool print_error_if_does_not_exist,
bool print_error_if_does_not_exist,
/*!< in: print detailed error
information to the .err log if a
matching tablespace is not found from
@ -931,7 +929,8 @@ fil_space_for_table_exists_in_mem(
bool adjust_space, /*!< in: whether to adjust space id
when find table space mismatch */
mem_heap_t* heap, /*!< in: heap memory */
table_id_t table_id); /*!< in: table id */
table_id_t table_id, /*!< in: table id */
ulint table_flags); /*!< in: table flags */
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
Extends all tablespaces to the size stored in the space header. During the

13
storage/innobase/include/fil0pagecompress.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2016 MariaDB Corporation. All Rights Reserved.
Copyright (C) 2013, 2017 MariaDB Corporation. All Rights Reserved.
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
@ -44,20 +44,11 @@ Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */
UNIV_INLINE
ibool
bool
fil_space_is_page_compressed(
/*=========================*/
ulint id); /*!< in: space id */
/*******************************************************************//**
Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */
UNIV_INTERN
ibool
fil_space_get_page_compressed(
/*=========================*/
fil_space_t* space); /*!< in: space id */
/*******************************************************************//**
Returns the atomic writes flag of the space, or false if the space
is not using atomic writes. The tablespace must be cached in the memory cache.
@return atomic write table option value */

430
storage/innobase/include/fsp0fsp.h

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -52,28 +52,67 @@ to the two Barracuda row formats COMPRESSED and DYNAMIC. */
#define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1
/** Number of flag bits used to indicate the tablespace page size */
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
/** Width of the DATA_DIR flag. This flag indicates that the tablespace
is found in a remote location, not the default data directory. */
#define FSP_FLAGS_WIDTH_DATA_DIR 1
/** Number of flag bits used to indicate the page compression and compression level */
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL 4
/** Number of reserved bits */
#define FSP_FLAGS_WIDTH_RESERVED 6
/** Number of flag bits used to indicate the page compression */
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1
/** Number of flag bits used to indicate atomic writes for this tablespace */
#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 2
/** Width of all the currently known tablespace flags */
/** Width of all the currently known persistent tablespace flags */
#define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \
+ FSP_FLAGS_WIDTH_ZIP_SSIZE \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_PAGE_SSIZE \
+ FSP_FLAGS_WIDTH_DATA_DIR \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL \
+ FSP_FLAGS_WIDTH_ATOMIC_WRITES )
/** A mask of all the known/used bits in tablespace flags */
#define FSP_FLAGS_MASK (~(~0 << FSP_FLAGS_WIDTH))
+ FSP_FLAGS_WIDTH_RESERVED \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION)
/** A mask of all the known/used bits in FSP_SPACE_FLAGS */
#define FSP_FLAGS_MASK (~(~0U << FSP_FLAGS_WIDTH))
/* FSP_SPACE_FLAGS position and name in MySQL 5.6/MariaDB 10.0 or older
and MariaDB 10.1.20 or older MariaDB 10.1 and in MariaDB 10.1.21
or newer.
MySQL 5.6 MariaDB 10.1.x MariaDB 10.1.21
====================================================================
Below flags in same offset
====================================================================
0: POST_ANTELOPE 0:POST_ANTELOPE 0: POST_ANTELOPE
1..4: ZIP_SSIZE(0..5) 1..4:ZIP_SSIZE(0..5) 1..4: ZIP_SSIZE(0..5)
(NOTE: bit 4 is always 0)
5: ATOMIC_BLOBS 5:ATOMIC_BLOBS 5: ATOMIC_BLOBS
=====================================================================
Below note the order difference:
=====================================================================
6..9: PAGE_SSIZE(3..7) 6: COMPRESSION 6..9: PAGE_SSIZE(3..7)
10: DATA_DIR 7..10: COMP_LEVEL(0..9) 10: RESERVED (5.6 DATA_DIR)
=====================================================================
The flags below were in incorrect position in MariaDB 10.1,
or have been introduced in MySQL 5.7 or 8.0:
=====================================================================
11: UNUSED 11..12:ATOMIC_WRITES 11: RESERVED (5.7 SHARED)
12: RESERVED (5.7 TEMPORARY)
13..15:PAGE_SSIZE(3..7) 13: RESERVED (5.7 ENCRYPTION)
14: RESERVED (8.0 SDI)
15: RESERVED
16: PAGE_SSIZE_msb(0) 16: COMPRESSION
17: DATA_DIR 17: UNUSED
18: UNUSED
=====================================================================
The flags below only exist in fil_space_t::flags, not in FSP_SPACE_FLAGS:
=====================================================================
25: DATA_DIR
26..27: ATOMIC_WRITES
28..31: COMPRESSION_LEVEL
*/
/** A mask of the memory-only flags in fil_space_t::flags */
#define FSP_FLAGS_MEM_MASK (~0U << FSP_FLAGS_MEM_DATA_DIR)
/** Zero relative shift position of the DATA_DIR flag */
#define FSP_FLAGS_MEM_DATA_DIR 25
/** Zero relative shift position of the ATOMIC_WRITES field */
#define FSP_FLAGS_MEM_ATOMIC_WRITES 26
/** Zero relative shift position of the COMPRESSION_LEVEL field */
#define FSP_FLAGS_MEM_COMPRESSION_LEVEL 28
/** Zero relative shift position of the POST_ANTELOPE field */
#define FSP_FLAGS_POS_POST_ANTELOPE 0
@ -83,29 +122,16 @@ is found in a remote location, not the default data directory. */
/** Zero relative shift position of the ATOMIC_BLOBS field */
#define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \
+ FSP_FLAGS_WIDTH_ZIP_SSIZE)
/** Note that these need to be before the page size to be compatible with
dictionary */
/** Zero relative shift position of the PAGE_COMPRESSION field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL (FSP_FLAGS_POS_PAGE_COMPRESSION \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION)
/** Zero relative shift position of the ATOMIC_WRITES field */
#define FSP_FLAGS_POS_ATOMIC_WRITES (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)
/** Zero relative shift position of the PAGE_SSIZE field */
#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_WRITES \
+ FSP_FLAGS_WIDTH_ATOMIC_WRITES)
/** Zero relative shift position of the start of the UNUSED bits */
#define FSP_FLAGS_POS_DATA_DIR (FSP_FLAGS_POS_PAGE_SSIZE \
+ FSP_FLAGS_WIDTH_PAGE_SSIZE)
#define FSP_FLAGS_POS_DATA_DIR_ORACLE (FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS \
/** Zero relative shift position of the start of the PAGE_SSIZE bits */
#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
/** Zero relative shift position of the start of the RESERVED bits
these are only used in MySQL 5.7 and used for compatibility. */
#define FSP_FLAGS_POS_RESERVED (FSP_FLAGS_POS_PAGE_SSIZE \
+ FSP_FLAGS_WIDTH_PAGE_SSIZE)
/** Zero relative shift position of the start of the UNUSED bits */
#define FSP_FLAGS_POS_UNUSED (FSP_FLAGS_POS_DATA_DIR \
+ FSP_FLAGS_WIDTH_DATA_DIR)
/** Zero relative shift position of the PAGE_COMPRESSION field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_RESERVED \
+ FSP_FLAGS_WIDTH_RESERVED)
/** Bit mask of the POST_ANTELOPE field */
#define FSP_FLAGS_MASK_POST_ANTELOPE \
@ -123,26 +149,23 @@ dictionary */
#define FSP_FLAGS_MASK_PAGE_SSIZE \
((~(~0U << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** Bit mask of the DATA_DIR field */
#define FSP_FLAGS_MASK_DATA_DIR \
((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \
<< FSP_FLAGS_POS_DATA_DIR)
/** Bit mask of the DATA_DIR field */
#define FSP_FLAGS_MASK_DATA_DIR_ORACLE \
((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \
<< FSP_FLAGS_POS_DATA_DIR_ORACLE)
/** Bit mask of the RESERVED1 field */
#define FSP_FLAGS_MASK_RESERVED \
((~(~0U << FSP_FLAGS_WIDTH_RESERVED)) \
<< FSP_FLAGS_POS_RESERVED)
/** Bit mask of the PAGE_COMPRESSION field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION \
#define FSP_FLAGS_MASK_PAGE_COMPRESSION \
((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \
<< FSP_FLAGS_POS_PAGE_COMPRESSION)
/** Bit mask of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL \
((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)) \
<< FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)
/** Bit mask of the ATOMIC_WRITES field */
#define FSP_FLAGS_MASK_ATOMIC_WRITES \
((~(~0U << FSP_FLAGS_WIDTH_ATOMIC_WRITES)) \
<< FSP_FLAGS_POS_ATOMIC_WRITES)
/** Bit mask of the in-memory ATOMIC_WRITES field */
#define FSP_FLAGS_MASK_MEM_ATOMIC_WRITES \
(3U << FSP_FLAGS_MEM_ATOMIC_WRITES)
/** Bit mask of the in-memory COMPRESSION_LEVEL field */
#define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \
(15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL)
/** Return the value of the POST_ANTELOPE field */
#define FSP_FLAGS_GET_POST_ANTELOPE(flags) \
((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \
@ -159,49 +182,78 @@ dictionary */
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
>> FSP_FLAGS_POS_PAGE_SSIZE)
/** Return the value of the DATA_DIR field */
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
((flags & FSP_FLAGS_MASK_DATA_DIR) \
>> FSP_FLAGS_POS_DATA_DIR)
#define FSP_FLAGS_HAS_DATA_DIR_ORACLE(flags) \
((flags & FSP_FLAGS_MASK_DATA_DIR_ORACLE) \
>> FSP_FLAGS_POS_DATA_DIR_ORACLE)
/** @return the RESERVED flags */
#define FSP_FLAGS_GET_RESERVED(flags) \
((flags & FSP_FLAGS_MASK_RESERVED) \
>> FSP_FLAGS_POS_RESERVED)
/** @return the PAGE_COMPRESSION flag */
#define FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION)
/** Return the contents of the UNUSED bits */
#define FSP_FLAGS_GET_UNUSED(flags) \
(flags >> FSP_FLAGS_POS_UNUSED)
/** Return the value of the PAGE_COMPRESSION field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION)
/** Return the value of the PAGE_COMPRESSION_LEVEL field */
/** @return the PAGE_SSIZE flags for the current innodb_page_size */
#define FSP_FLAGS_PAGE_SSIZE() \
((UNIV_PAGE_SIZE == UNIV_PAGE_SIZE_ORIG) ? \
0 : (UNIV_PAGE_SIZE_SHIFT - UNIV_ZIP_SIZE_SHIFT_MIN + 1) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** @return the value of the DATA_DIR field */
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
(flags & 1U << FSP_FLAGS_MEM_DATA_DIR)
/** @return the COMPRESSION_LEVEL field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)
/** Return the value of the ATOMIC_WRITES field */
((flags & FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL) \
>> FSP_FLAGS_MEM_COMPRESSION_LEVEL)
/** @return the ATOMIC_WRITES field */
#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \
((flags & FSP_FLAGS_MASK_ATOMIC_WRITES) \
>> FSP_FLAGS_POS_ATOMIC_WRITES)
/** Set a PAGE_SSIZE into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize) \
(flags | (ssize << FSP_FLAGS_POS_PAGE_SSIZE))
((flags & FSP_FLAGS_MASK_MEM_ATOMIC_WRITES) \
>> FSP_FLAGS_MEM_ATOMIC_WRITES)
/** Set a PAGE_COMPRESSION into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_PAGE_COMPRESSION(flags, compression) \
(flags | (compression << FSP_FLAGS_POS_PAGE_COMPRESSION))
/* Compatibility macros for MariaDB 10.1.20 or older 10.1 see
table above. */
/** Zero relative shift position of the PAGE_COMPRESSION field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 \
(FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 \
(FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 + 1)
/** Zero relative shift position of the ATOMIC_WRITES field */
#define FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 \
(FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 + 4)
/** Zero relative shift position of the PAGE_SSIZE field */
#define FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101 \
(FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 + 2)
/** Set a PAGE_COMPRESSION_LEVEL into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, level) \
(flags | (level << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL))
/** Bit mask of the PAGE_COMPRESSION field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101 \
(1U << FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101)
/** Bit mask of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101 \
(15U << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101)
/** Bit mask of the ATOMIC_WRITES field */
#define FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101 \
(3U << FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101)
/** Bit mask of the PAGE_SSIZE field */
#define FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101 \
(15U << FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101)
/** Set a ATOMIC_WRITES into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomics) \
(flags | (atomics << FSP_FLAGS_POS_ATOMIC_WRITES))
/** Return the value of the PAGE_COMPRESSION field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101)
/** Return the value of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101)
/** Return the value of the PAGE_SSIZE field */
#define FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags) \
((flags & FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101) \
>> FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101)
/* @} */
@ -735,19 +787,193 @@ fseg_print(
mtr_t* mtr); /*!< in/out: mini-transaction */
#endif /* UNIV_BTR_PRINT */
/********************************************************************//**
Validate and return the tablespace flags, which are stored in the
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
have a file format number plus the DICT_TF_COMPACT bit set.
@return true if check ok */
/** Validate the tablespace flags, which are stored in the
tablespace header at offset FSP_SPACE_FLAGS.
@param[in] flags the contents of FSP_SPACE_FLAGS
@return whether the flags are correct (not in the buggy 10.1) format */
MY_ATTRIBUTE((warn_unused_result, const))
UNIV_INLINE
bool
fsp_flags_is_valid(
/*===============*/
ulint flags) /*!< in: tablespace flags */
MY_ATTRIBUTE((warn_unused_result, const));
fsp_flags_is_valid(ulint flags)
{
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
return(false););
if (flags == 0) {
return(true);
}
if (flags & ~FSP_FLAGS_MASK) {
return(false);
}
if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS))
== FSP_FLAGS_MASK_ATOMIC_BLOBS) {
/* If the "atomic blobs" flag (indicating
ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag
is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag
must also be set. */
return(false);
}
/* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag
of MySQL 5.6 and MariaDB 10.0, which we ignore.
In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20,
bits 10..14 would be nonzero 0bsssaa where sss is
nonzero PAGE_SSIZE (3, 4, 6, or 7)
and aa is ATOMIC_WRITES (not 0b11). */
if (FSP_FLAGS_GET_RESERVED(flags) & ~1) {
return(false);
}
const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) {
/* the page_size is not between 4k and 64k;
16k should be encoded as 0, not 5 */
return(false);
}
const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
if (zssize == 0) {
/* not ROW_FORMAT=COMPRESSED */
} else if (zssize > (ssize ? ssize : 5)) {
/* invalid KEY_BLOCK_SIZE */
return(false);
} else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE
| FSP_FLAGS_MASK_ATOMIC_BLOBS)) {
/* both these flags should be set for
ROW_FORMAT=COMPRESSED */
return(false);
}
return(true);
}
/** Convert FSP_SPACE_FLAGS from the buggy MariaDB 10.1.0..10.1.20 format.
@param[in] flags the contents of FSP_SPACE_FLAGS
@return the flags corrected from the buggy MariaDB 10.1 format
@retval ULINT_UNDEFINED if the flags are not in the buggy 10.1 format */
MY_ATTRIBUTE((warn_unused_result, const))
UNIV_INLINE
ulint
fsp_flags_convert_from_101(ulint flags)
{
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
return(ULINT_UNDEFINED););
if (flags == 0) {
return(flags);
}
if (flags >> 18) {
/* The most significant FSP_SPACE_FLAGS bit that was ever set
by MariaDB 10.1.0 to 10.1.20 was bit 17 (misplaced DATA_DIR flag).
The flags must be less than 1<<18 in order to be valid. */
return(ULINT_UNDEFINED);
}
if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS))
== FSP_FLAGS_MASK_ATOMIC_BLOBS) {
/* If the "atomic blobs" flag (indicating
ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag
is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag
must also be set. */
return(ULINT_UNDEFINED);
}
/* Bits 6..10 denote compression in MariaDB 10.1.0 to 10.1.20.
They must be either 0b00000 or 0b00011 through 0b10011.
In correct versions, these bits would be
0bd0sss where d is the DATA_DIR flag (garbage bit) and
sss is the PAGE_SSIZE (3, 4, 6, or 7).
NOTE: MariaDB 10.1.0 to 10.1.20 can misinterpret
uncompressed data files with innodb_page_size=4k or 64k as
compressed innodb_page_size=16k files. Below is an exhaustive
state space analysis.
-0by1zzz: impossible (the bit 4 must be clean; see above)
-0b101xx: DATA_DIR, innodb_page_size>4k: invalid (COMPRESSION_LEVEL>9)
+0bx0011: innodb_page_size=4k:
!!! Misinterpreted as COMPRESSION_LEVEL=9 or 1, COMPRESSION=1.
-0bx0010: impossible, because sss must be 0b011 or 0b1xx
-0bx0001: impossible, because sss must be 0b011 or 0b1xx
-0b10000: DATA_DIR, innodb_page_size=16:
invalid (COMPRESSION_LEVEL=8 but COMPRESSION=0)
+0b00111: no DATA_DIR, innodb_page_size=64k:
!!! Misinterpreted as COMPRESSION_LEVEL=3, COMPRESSION=1.
-0b00101: impossible, because sss must be 0 for 16k, not 0b101
-0b001x0: no DATA_DIR, innodb_page_size=32k or 8k:
invalid (COMPRESSION_LEVEL=3 but COMPRESSION=0)
+0b00000: innodb_page_size=16k (looks like COMPRESSION=0)
??? Could actually be compressed; see PAGE_SSIZE below */
const ulint level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101(
flags);
if (FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) != (level != 0)
|| level > 9) {
/* The compression flags are not in the buggy MariaDB
10.1 format. */
return(ULINT_UNDEFINED);
}
if (!(~flags & FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101)) {
/* The ATOMIC_WRITES flags cannot be 0b11.
(The bits 11..12 should actually never be 0b11,
because in MySQL they would be SHARED|TEMPORARY.) */
return(ULINT_UNDEFINED);
}
/* Bits 13..16 are the wrong position for PAGE_SSIZE, and they
should contain one of the values 3,4,6,7, that is, be of the form
0b0011 or 0b01xx (except 0b0110).
In correct versions, these bits should be 0bc0se
where c is the MariaDB COMPRESSED flag
and e is the MySQL 5.7 ENCRYPTION flag
and s is the MySQL 8.0 SDI flag. MariaDB can only support s=0, e=0.
Compressed innodb_page_size=16k tables with correct FSP_SPACE_FLAGS
will be properly rejected by older MariaDB 10.1.x because they
would read as PAGE_SSIZE>=8 which is not valid. */
const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags);
if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) {
/* the page_size is not between 4k and 64k;
16k should be encoded as 0, not 5 */
return(ULINT_UNDEFINED);
}
const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
if (zssize == 0) {
/* not ROW_FORMAT=COMPRESSED */
} else if (zssize > (ssize ? ssize : 5)) {
/* invalid KEY_BLOCK_SIZE */
return(ULINT_UNDEFINED);
} else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE
| FSP_FLAGS_MASK_ATOMIC_BLOBS)) {
/* both these flags should be set for
ROW_FORMAT=COMPRESSED */
return(ULINT_UNDEFINED);
}
flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE
| FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags)
<< FSP_FLAGS_POS_PAGE_COMPRESSION);
ut_ad(fsp_flags_is_valid(flags));
return(flags);
}
/** Compare tablespace flags.
@param[in] expected expected flags from dict_tf_to_fsp_flags()
@param[in] actual flags read from FSP_SPACE_FLAGS
@return whether the flags match */
MY_ATTRIBUTE((warn_unused_result))
UNIV_INLINE
bool
fsp_flags_match(ulint expected, ulint actual)
{
expected &= ~FSP_FLAGS_MEM_MASK;
ut_ad(fsp_flags_is_valid(expected));
if (actual == expected) {
return(true);
}
actual = fsp_flags_convert_from_101(actual);
return(actual == expected);
}
/********************************************************************//**
Determine if the tablespace is compressed from dict_table_t::flags.
@return TRUE if compressed, FALSE if not compressed */

153
storage/innobase/include/fsp0fsp.ic

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
Copyright (c) 2013, 2017, 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
@ -46,107 +46,6 @@ fsp_descr_page(
return((page_no & (zip_size - 1)) == FSP_XDES_OFFSET);
}
/********************************************************************//**
Validate and return the tablespace flags, which are stored in the
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
have a file format number plus the DICT_TF_COMPACT bit set.
@return true if check ok */
UNIV_INLINE
bool
fsp_flags_is_valid(
/*===============*/
ulint flags) /*!< in: tablespace flags */
{
ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(flags);
ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
ulint unused = FSP_FLAGS_GET_UNUSED(flags);
ulint page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags);
ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags);
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false););
/* fsp_flags is zero unless atomic_blobs is set. */
/* Make sure there are no bits that we do not know about. */
if (unused != 0 || flags == 1) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted unused %lu\n",
flags, unused);
return(false);
} else if (post_antelope) {
/* The Antelope row formats REDUNDANT and COMPACT did
not use tablespace flags, so this flag and the entire
4-byte field is zero for Antelope row formats. */
if (!atomic_blobs) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_blobs %lu\n",
flags, atomic_blobs);
return(false);
}
}
if (!atomic_blobs) {
/* Barracuda row formats COMPRESSED and DYNAMIC build on
the page structure introduced for the COMPACT row format
by allowing long fields to be broken into prefix and
externally stored parts. */
if (post_antelope || zip_ssize != 0) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu atomic_blobs %lu\n",
flags, zip_ssize, atomic_blobs);
return(false);
}
} else if (!post_antelope || zip_ssize > PAGE_ZIP_SSIZE_MAX) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu max %d\n",
flags, zip_ssize, PAGE_ZIP_SSIZE_MAX);
return(false);
} else if (page_ssize > UNIV_PAGE_SSIZE_MAX) {
/* The page size field can be used for any row type, or it may
be zero for an original 16k page size.
Validate the page shift size is within allowed range. */
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu\n",
flags, page_ssize, UNIV_PAGE_SSIZE_MAX);
return(false);
} else if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_ORIG && !page_ssize) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu:%d\n",
flags, page_ssize, UNIV_PAGE_SIZE, UNIV_PAGE_SIZE_ORIG);
return(false);
}
/* Page compression level requires page compression and atomic blobs
to be set */
if (page_compression_level || page_compression) {
if (!page_compression || !atomic_blobs) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_compression %lu\n"
"InnoDB: Error: page_compression_level %lu atomic_blobs %lu\n",
flags, page_compression, page_compression_level, atomic_blobs);
return(false);
}
}
if (atomic_writes > ATOMIC_WRITES_OFF) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_writes %lu\n",
flags, atomic_writes);
return (false);
}
#if UNIV_FORMAT_MAX != UNIV_FORMAT_B
# error "UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations."
#endif
/* The DATA_DIR field can be used for any row type so there is
nothing here to validate. */
return(true);
}
/********************************************************************//**
Determine if the tablespace is compressed from dict_table_t::flags.
@return TRUE if compressed, FALSE if not compressed */
@ -191,10 +90,10 @@ UNIV_INLINE
ulint
fsp_flags_get_page_size(
/*====================*/
ulint flags) /*!< in: tablespace flags */
ulint flags) /*!< in: tablespace flags */
{
ulint page_size = 0;
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
ulint page_size = 0;
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
/* Convert from a 'log2 minus 9' to a page size in bytes. */
if (UNIV_UNLIKELY(ssize)) {
@ -211,50 +110,6 @@ fsp_flags_get_page_size(
}
#ifndef UNIV_INNOCHECKSUM
/********************************************************************//**
Add the page size to the tablespace flags.
@return tablespace flags after page size is added */
UNIV_INLINE
ulint
fsp_flags_set_page_size(
/*====================*/
ulint flags, /*!< in: tablespace flags */
ulint page_size) /*!< in: page size in bytes */
{
ulint ssize = 0;
ulint shift;
/* Page size should be > UNIV_PAGE_SIZE_MIN */
ut_ad(page_size >= UNIV_PAGE_SIZE_MIN);
ut_ad(page_size <= UNIV_PAGE_SIZE_MAX);
if (page_size == UNIV_PAGE_SIZE_ORIG) {
ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags));
return(flags);
}
for (shift = UNIV_PAGE_SIZE_SHIFT_MAX;
shift >= UNIV_PAGE_SIZE_SHIFT_MIN;
shift--) {
ulint mask = (1 << shift);
if (page_size & mask) {
ut_ad(!(page_size & ~mask));
ssize = shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1;
break;
}
}
ut_ad(ssize);
ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX);
flags = FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize);
ut_ad(fsp_flags_is_valid(flags));
return(flags);
}
/********************************************************************//**
Calculates the descriptor index within a descriptor page.
@return descriptor index */

11
storage/innobase/include/fsp0pagecompress.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -47,15 +47,6 @@ fsp_header_get_compression_level(
/*=============================*/
const page_t* page); /*!< in: first page of a tablespace */
/********************************************************************//**
Determine if the tablespace is page compressed from dict_table_t::flags.
@return TRUE if page compressed, FALSE if not compressed */
UNIV_INLINE
ibool
fsp_flags_is_page_compressed(
/*=========================*/
ulint flags); /*!< in: tablespace flags */
/********************************************************************//**
Extract the page compression level from tablespace flags.
A tablespace has only one physical page compression level

28
storage/innobase/include/fsp0pagecompress.ic

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -25,18 +25,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@mariadb.com
***********************************************************************/
/********************************************************************//**
Determine if the tablespace is page compressed from dict_table_t::flags.
@return TRUE if page compressed, FALSE if not page compressed */
UNIV_INLINE
ibool
fsp_flags_is_page_compressed(
/*=========================*/
ulint flags) /*!< in: tablespace flags */
{
return(FSP_FLAGS_GET_PAGE_COMPRESSION(flags));
}
/********************************************************************//**
Determine the tablespace is page compression level from dict_table_t::flags.
@return page compression level or 0 if not compressed*/
@ -125,21 +113,15 @@ Extract the page compression from space.
@return true if space is page compressed, false if space is not found
or space is not page compressed. */
UNIV_INLINE
ibool
bool
fil_space_is_page_compressed(
/*=========================*/
ulint id) /*!< in: space id */
{
ulint flags;
flags = fil_space_get_flags(id);
if (flags && flags != ULINT_UNDEFINED) {
return(fsp_flags_is_page_compressed(flags));
}
ulint flags = fil_space_get_flags(id);
return(0);
return(flags != ULINT_UNDEFINED
&& FSP_FLAGS_HAS_PAGE_COMPRESSION(flags));
}
#endif /* UNIV_INNOCHECKSUM */

94
storage/innobase/row/row0import.cc

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2016, MariaDB Corporation.
Copyright (c) 2015, 2017, 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
@ -371,8 +371,7 @@ public:
m_space(ULINT_UNDEFINED),
m_xdes(),
m_xdes_page_no(ULINT_UNDEFINED),
m_space_flags(ULINT_UNDEFINED),
m_table_flags(ULINT_UNDEFINED) UNIV_NOTHROW { }
m_space_flags(ULINT_UNDEFINED) UNIV_NOTHROW { }
/**
Free any extent descriptor instance */
@ -535,10 +534,6 @@ protected:
/** Flags value read from the header page */
ulint m_space_flags;
/** Derived from m_space_flags and row format type, the row format
type is determined from the page header. */
ulint m_table_flags;
};
/** Determine the page size to use for traversing the tablespace
@ -553,6 +548,19 @@ AbstractCallback::init(
const page_t* page = block->frame;
m_space_flags = fsp_header_get_flags(page);
if (!fsp_flags_is_valid(m_space_flags)) {
ulint cflags = fsp_flags_convert_from_101(m_space_flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Invalid FSP_SPACE_FLAGS=0x%x",
int(m_space_flags));
return(DB_CORRUPTION);
}
m_space_flags = cflags;
}
/* Clear the DATA_DIR flag, which is basically garbage. */
m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED);
/* Since we don't know whether it is a compressed table
or not, the data is always read into the block->frame. */
@ -640,46 +648,6 @@ struct FetchIndexRootPages : public AbstractCallback {
return(m_space);
}
/**
Check if the .ibd file row format is the same as the table's.
@param ibd_table_flags - determined from space and page.
@return DB_SUCCESS or error code. */
dberr_t check_row_format(ulint ibd_table_flags) UNIV_NOTHROW
{
dberr_t err;
rec_format_t ibd_rec_format;
rec_format_t table_rec_format;
if (!dict_tf_is_valid(ibd_table_flags)) {
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
".ibd file has invlad table flags: %lx",
ibd_table_flags);
return(DB_CORRUPTION);
}
ibd_rec_format = dict_tf_get_rec_format(ibd_table_flags);
table_rec_format = dict_tf_get_rec_format(m_table->flags);
if (table_rec_format != ibd_rec_format) {
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
"Table has %s row format, .ibd "
"file has %s row format.",
dict_tf_to_row_format_string(m_table->flags),
dict_tf_to_row_format_string(ibd_table_flags));
err = DB_CORRUPTION;
} else {
err = DB_SUCCESS;
}
return(err);
}
/**
Called for each block as it is read from the file.
@param offset - physical offset in the file
@ -743,12 +711,17 @@ FetchIndexRootPages::operator() (
m_indexes.push_back(Index(id, page_no));
if (m_indexes.size() == 1) {
m_table_flags = dict_sys_tables_type_to_tf(
m_space_flags,
page_is_comp(page) ? DICT_N_COLS_COMPACT : 0);
err = check_row_format(m_table_flags);
/* Check that the tablespace flags match the table flags. */
ulint expected = dict_tf_to_fsp_flags(m_table->flags);
if (!fsp_flags_match(expected, m_space_flags)) {
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
"Expected FSP_SPACE_FLAGS=0x%x, .ibd "
"file contains 0x%x.",
unsigned(expected),
unsigned(m_space_flags));
return(DB_CORRUPTION);
}
}
}
@ -1965,21 +1938,14 @@ PageConverter::update_header(
"- ignored");
}
ulint space_flags = fsp_header_get_flags(get_frame(block));
if (!fsp_flags_is_valid(space_flags)) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Unsupported tablespace format %lu",
(ulong) space_flags);
return(DB_UNSUPPORTED);
}
mach_write_to_8(
get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
m_current_lsn);
/* Write back the adjusted flags. */
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ get_frame(block), m_space_flags);
/* Write space_id to the tablespace header, page 0. */
mach_write_to_4(
get_frame(block) + FSP_HEADER_OFFSET + FSP_SPACE_ID,

11
storage/innobase/row/row0mysql.cc

@ -4335,6 +4335,7 @@ row_drop_table_for_mysql(
switch (err) {
ibool is_temp;
ulint table_flags;
case DB_SUCCESS:
/* Clone the name, in case it has been allocated
@ -4343,6 +4344,7 @@ row_drop_table_for_mysql(
space_id = table->space;
ibd_file_missing = table->ibd_file_missing;
table_flags = table->flags;
is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY);
/* If there is a temp path then the temp flag is set.
@ -4358,9 +4360,9 @@ row_drop_table_for_mysql(
}
/* We do not allow temporary tables with a remote path. */
ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table->flags)));
ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table_flags)));
if (space_id && DICT_TF_HAS_DATA_DIR(table->flags)) {
if (space_id && DICT_TF_HAS_DATA_DIR(table_flags)) {
dict_get_and_save_data_dir_path(table, true);
ut_a(table->data_dir_path);
@ -4426,8 +4428,9 @@ row_drop_table_for_mysql(
if (err == DB_SUCCESS && space_id > TRX_SYS_SPACE) {
if (!is_temp
&& !fil_space_for_table_exists_in_mem(
space_id, tablename, FALSE,
print_msg, false, NULL, 0)) {
space_id, tablename,
print_msg, false, NULL, 0,
table_flags)) {
/* This might happen if we are dropping a
discarded tablespace */
err = DB_SUCCESS;

18
storage/innobase/srv/srv0start.cc

@ -673,8 +673,7 @@ create_log_files(
sprintf(logfilename + dirnamelen, "ib_logfile%u", INIT_LOG_FILE0);
fil_space_create(
logfilename, SRV_LOG_SPACE_FIRST_ID,
fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
logfilename, SRV_LOG_SPACE_FIRST_ID, 0,
FIL_LOG,
NULL /* no encryption yet */,
true /* this is create */);
@ -1159,7 +1158,7 @@ check_first_page:
crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
}
flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE);
flags = FSP_FLAGS_PAGE_SSIZE();
fil_space_create(name, 0, flags, FIL_TABLESPACE,
crypt_data, (*create_new_db) == true);
@ -1307,7 +1306,7 @@ srv_undo_tablespace_open(
fil_set_max_space_id_if_bigger(space);
/* Set the compressed page size to 0 (non-compressed) */
flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE);
flags = FSP_FLAGS_PAGE_SSIZE();
fil_space_create(name, space, flags, FIL_TABLESPACE,
NULL /* no encryption */,
true /* create */);
@ -2296,9 +2295,7 @@ innobase_start_or_create_for_mysql(void)
sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
fil_space_create(logfilename,
SRV_LOG_SPACE_FIRST_ID,
fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
FIL_LOG,
SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG,
NULL /* no encryption yet */,
true /* create */);
@ -2714,6 +2711,13 @@ files_checked:
}
if (!srv_read_only_mode) {
const ulint flags = FSP_FLAGS_PAGE_SSIZE();
for (ulint id = 0; id <= srv_undo_tablespaces; id++) {
if (fil_space_get(id)) {
fsp_flags_try_adjust(id, flags);
}
}
/* Create the thread which watches the timeouts
for lock waits */
thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create(

15
storage/xtradb/buf/buf0dblwr.cc

@ -589,6 +589,21 @@ buf_dblwr_process()
continue;
}
if (page_no == 0) {
/* Check the FSP_SPACE_FLAGS. */
ulint flags = fsp_header_get_flags(page);
if (!fsp_flags_is_valid(flags)
&& fsp_flags_convert_from_101(flags)
== ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_WARN,
"Ignoring a doublewrite copy of page "
ULINTPF ":0 due to invalid flags 0x%x",
space_id, int(flags));
continue;
}
/* The flags on the page should be converted later. */
}
/* Write the good page from the doublewrite buffer to
the intended position. */

20
storage/xtradb/dict/dict0load.cc

@ -1052,8 +1052,6 @@ loop:
btr_pcur_store_position(&pcur, &mtr);
mtr_commit(&mtr);
/* For tables created with old versions of InnoDB,
SYS_TABLES.MIX_LEN may contain garbage. Such tables
would always be in ROW_FORMAT=REDUNDANT. Pretend that
@ -1087,16 +1085,19 @@ loop:
if (space_id == 0) {
/* The system tablespace always exists. */
ut_ad(!discarded);
goto next_tablespace;
mem_free(name);
goto loop;
}
mtr_commit(&mtr);
switch (dict_check) {
case DICT_CHECK_ALL_LOADED:
/* All tablespaces should have been found in
fil_load_single_table_tablespaces(). */
if (fil_space_for_table_exists_in_mem(
space_id, name, TRUE, !(is_temp || discarded),
false, NULL, 0)
space_id, name, !(is_temp || discarded),
false, NULL, 0, flags)
&& !(is_temp || discarded)) {
/* If user changes the path of .ibd files in
*.isl files before doing crash recovery ,
@ -1128,8 +1129,8 @@ loop:
/* Some tablespaces may have been opened in
trx_resurrect_table_locks(). */
if (fil_space_for_table_exists_in_mem(
space_id, name, FALSE, FALSE,
false, NULL, 0)) {
space_id, name, false,
false, NULL, 0, flags)) {
break;
}
/* fall through */
@ -1191,7 +1192,6 @@ loop:
max_space_id = space_id;
}
next_tablespace:
mem_free(name);
mtr_start(&mtr);
@ -2383,8 +2383,8 @@ err_exit:
table->ibd_file_missing = TRUE;
} else if (!fil_space_for_table_exists_in_mem(
table->space, name, FALSE, FALSE, true, heap,
table->id)) {
table->space, name, false, true, heap,
table->id, table->flags)) {
if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
/* Do not bother to retry opening temporary tables. */

395
storage/xtradb/fil/fil0fil.cc

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2013, 2017, 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
@ -601,10 +601,7 @@ fil_node_open_file(
ibool success;
byte* buf2;
byte* page;
ulint space_id;
ulint flags=0;
ulint page_size;
ulint atomic_writes=0;
ut_ad(mutex_own(&(system->mutex)));
ut_a(node->n_pending == 0);
@ -626,8 +623,6 @@ fil_node_open_file(
/* The following call prints an error message */
os_file_get_last_error(true);
ut_print_timestamp(stderr);
ib_logf(IB_LOG_LEVEL_WARN, "InnoDB: Error: cannot "
"open %s\n. InnoDB: Have you deleted .ibd "
"files under a running mysqld server?\n",
@ -653,17 +648,13 @@ fil_node_open_file(
ut_a(fil_is_user_tablespace_id(space->id));
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Error: the size of single-table"
" tablespace file %s\n"
"InnoDB: is only " UINT64PF ","
" should be at least %lu!\n",
node->name,
size_bytes,
(ulong) (FIL_IBD_FILE_INITIAL_SIZE
* UNIV_PAGE_SIZE));
ut_a(0);
ib_logf(IB_LOG_LEVEL_ERROR,
"The size of the file %s is only " UINT64PF
" bytes, should be at least " ULINTPF,
node->name, size_bytes,
FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE);
os_file_close(node->handle);
return(false);
}
/* Read the first page of the tablespace */
@ -676,77 +667,34 @@ fil_node_open_file(
success = os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE);
srv_stats.page0_read.add(1);
space_id = fsp_header_get_space_id(page);
flags = fsp_header_get_flags(page);
page_size = fsp_flags_get_page_size(flags);
atomic_writes = fsp_flags_get_atomic_writes(flags);
const ulint space_id = fsp_header_get_space_id(page);
ulint flags = fsp_header_get_flags(page);
ut_free(buf2);
/* Close the file now that we have read the space id from it */
os_file_close(node->handle);
if (UNIV_UNLIKELY(space_id != space->id)) {
fprintf(stderr,
"InnoDB: Error: tablespace id is %lu"
" in the data dictionary\n"
"InnoDB: but in file %s it is %lu!\n",
space->id, node->name, space_id);
ut_error;
}
if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
|| space_id == 0)) {
fprintf(stderr,
"InnoDB: Error: tablespace id %lu"
" in file %s is not sensible\n",
(ulong) space_id, node->name);
ut_error;
}
if (UNIV_UNLIKELY(fsp_flags_get_page_size(space->flags)
!= page_size)) {
fprintf(stderr,
"InnoDB: Error: tablespace file %s"
" has page size 0x%lx\n"
"InnoDB: but the data dictionary"
" expects page size 0x%lx!\n",
node->name, flags,
fsp_flags_get_page_size(space->flags));
if (!fsp_flags_is_valid(flags)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Expected tablespace flags 0x%x"
" but found 0x%x in the file %s",
int(space->flags), int(flags),
node->name);
return(false);
}
ut_error;
flags = cflags;
}
if (UNIV_UNLIKELY(space->flags != flags)) {
ulint sflags = (space->flags & ~FSP_FLAGS_MASK_DATA_DIR);
ulint fflags = (flags & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
/* DATA_DIR option is on different place on MariaDB
compared to MySQL. If this is the difference. Fix
it. */
if (sflags == fflags) {
fprintf(stderr,
"InnoDB: Warning: Table flags 0x%lx"
" in the data dictionary but in file %s are 0x%lx!\n"
" Temporally corrected because DATA_DIR option to 0x%lx.\n",
space->flags, node->name, flags, space->flags);
flags = space->flags;
}
page_size = fsp_flags_get_page_size(flags);
if (!dict_tf_verify_flags(space->flags, flags)) {
fprintf(stderr,
"InnoDB: Error: table flags are 0x%lx"
" in the data dictionary\n"
"InnoDB: but the flags in file %s are 0x%lx!\n",
space->flags, node->name, flags);
ut_error;
}
if (UNIV_UNLIKELY(space_id != space->id)) {
ib_logf(IB_LOG_LEVEL_ERROR,
"tablespace id is " ULINTPF " in the data dictionary"
" but in file %s it is " ULINTPF "!\n",
space->id, node->name, space_id);
return(false);
}
if (size_bytes >= (1024*1024)) {
@ -768,7 +716,7 @@ add_size:
space->size += node->size;
}
atomic_writes = fsp_flags_get_atomic_writes(space->flags);
ulint atomic_writes = fsp_flags_get_atomic_writes(space->flags);
/* printf("Opening file %s\n", node->name); */
@ -1572,7 +1520,6 @@ fil_space_create(
fil_system->tablespace_version++;
space->tablespace_version = fil_system->tablespace_version;
space->mark = FALSE;
if (purpose == FIL_TABLESPACE && !recv_recovery_on
&& id > fil_system->max_assigned_id) {
@ -2324,27 +2271,21 @@ fil_write_flushed_lsn_to_data_files(
return(DB_SUCCESS);
}
/*******************************************************************//**
Checks the consistency of the first data page of a tablespace
/** Check the consistency of the first data page of a tablespace
at database startup.
@param[in] page page frame
@param[in] space_id tablespace identifier
@param[in] flags tablespace flags
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
static MY_ATTRIBUTE((warn_unused_result))
const char*
fil_check_first_page(
/*=================*/
const page_t* page) /*!< in: data page */
fil_check_first_page(const page_t* page, ulint space_id, ulint flags)
{
ulint space_id;
ulint flags;
if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) {
return(NULL);
}
space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page);
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
if (UNIV_PAGE_SIZE != fsp_flags_get_page_size(flags)) {
fprintf(stderr,
"InnoDB: Error: Current page size %lu != "
@ -2393,7 +2334,7 @@ fil_read_first_page(
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
ulint* flags, /*!< out: FSP_SPACE_FLAGS */
ulint* space_id, /*!< out: tablespace ID */
lsn_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
@ -2423,12 +2364,22 @@ fil_read_first_page(
*flags and *space_id as they were read from the first file and
do not validate the first page. */
if (!one_read_already) {
*flags = fsp_header_get_flags(page);
*space_id = fsp_header_get_space_id(page);
}
*flags = fsp_header_get_flags(page);
if (!one_read_already) {
check_msg = fil_check_first_page(page);
if (!fsp_flags_is_valid(*flags)) {
ulint cflags = fsp_flags_convert_from_101(*flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Invalid flags 0x%x in tablespace %u",
unsigned(*flags), unsigned(*space_id));
return "invalid tablespace flags";
} else {
*flags = cflags;
}
}
check_msg = fil_check_first_page(page, *space_id, *flags);
}
flushed_lsn = mach_read_from_8(page +
@ -2612,6 +2563,7 @@ fil_op_write_log(
ulint len;
log_ptr = mlog_open(mtr, 11 + 2 + 1);
ut_ad(fsp_flags_is_valid(flags));
if (!log_ptr) {
/* Logging in mtr is switched off during crash recovery:
@ -3823,7 +3775,7 @@ fil_create_new_single_table_tablespace(
ibool success;
/* TRUE if a table is created with CREATE TEMPORARY TABLE */
bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY);
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags);
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0;
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
fil_space_crypt_t *crypt_data = NULL;
@ -3831,7 +3783,7 @@ fil_create_new_single_table_tablespace(
ut_ad(!srv_read_only_mode);
ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
ut_a(fsp_flags_is_valid(flags));
ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK));
if (is_temp) {
/* Temporary table filepath */
@ -3924,12 +3876,9 @@ fil_create_new_single_table_tablespace(
memset(page, '\0', UNIV_PAGE_SIZE);
/* Add the UNIV_PAGE_SIZE to the table flags and write them to the
tablespace header. */
flags = fsp_flags_set_page_size(flags, UNIV_PAGE_SIZE);
flags |= FSP_FLAGS_PAGE_SSIZE();
fsp_header_init_fields(page, space_id, flags);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
ut_ad(fsp_flags_is_valid(flags));
if (!(fsp_flags_is_compressed(flags))) {
buf_flush_init_for_writing(page, NULL, 0);
@ -4008,7 +3957,8 @@ fil_create_new_single_table_tablespace(
fil_op_write_log(flags
? MLOG_FILE_CREATE2
: MLOG_FILE_CREATE,
space_id, mlog_file_flag, flags,
space_id, mlog_file_flag,
flags & ~FSP_FLAGS_MEM_MASK,
tablename, NULL, &mtr);
mtr_commit(&mtr);
@ -4072,6 +4022,39 @@ fil_report_bad_tablespace(
(ulong) expected_id, (ulong) expected_flags);
}
/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations.
(Typically when upgrading from MariaDB 10.1.0..10.1.20.)
@param[in] space_id tablespace ID
@param[in] flags desired tablespace flags */
UNIV_INTERN
void
fsp_flags_try_adjust(ulint space_id, ulint flags)
{
ut_ad(!srv_read_only_mode);
ut_ad(fsp_flags_is_valid(flags));
mtr_t mtr;
mtr_start(&mtr);
if (buf_block_t* b = buf_page_get(
space_id, fsp_flags_get_zip_size(flags), 0, RW_X_LATCH,
&mtr)) {
ulint f = fsp_header_get_flags(b->frame);
/* Suppress the message if only the DATA_DIR flag to differs. */
if ((f ^ flags) & ~(1U << FSP_FLAGS_POS_RESERVED)) {
ib_logf(IB_LOG_LEVEL_WARN,
"adjusting FSP_SPACE_FLAGS of tablespace "
ULINTPF " from 0x%x to 0x%x",
space_id, int(f), int(flags));
}
if (f != flags) {
mlog_write_ulint(FSP_HEADER_OFFSET
+ FSP_SPACE_FLAGS + b->frame,
flags, MLOG_4BYTES, &mtr);
}
}
mtr_commit(&mtr);
}
/********************************************************************//**
Tries to open a single-table tablespace and optionally checks that the
space id in it is correct. If this does not succeed, print an error message
@ -4101,7 +4084,7 @@ fil_open_single_table_tablespace(
bool validate, /*!< in: Do we validate tablespace? */
bool fix_dict, /*!< in: Can we fix the dictionary? */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
ulint flags, /*!< in: expected FSP_SPACE_FLAGS */
const char* tablename, /*!< in: table name in the
databasename/tablename format */
const char* path_in, /*!< in: tablespace filepath */
@ -4126,20 +4109,13 @@ fil_open_single_table_tablespace(
/* Table flags can be ULINT_UNDEFINED if
dict_tf_to_fsp_flags_failure is set. */
if (flags != ULINT_UNDEFINED) {
if (!fsp_flags_is_valid(flags)) {
return(DB_CORRUPTION);
}
} else {
if (flags == ULINT_UNDEFINED) {
return(DB_CORRUPTION);
}
ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK));
atomic_writes = fsp_flags_get_atomic_writes(flags);
/* If the tablespace was relocated, we do not
compare the DATA_DIR flag */
ulint mod_flags = flags & ~FSP_FLAGS_MASK_DATA_DIR;
memset(&def, 0, sizeof(def));
memset(&dict, 0, sizeof(dict));
memset(&remote, 0, sizeof(remote));
@ -4217,31 +4193,17 @@ fil_open_single_table_tablespace(
def.check_msg = fil_read_first_page(
def.file, FALSE, &def.flags, &def.id,
&def.lsn, &def.lsn, &def.crypt_data);
def.valid = !def.check_msg;
if (table) {
table->crypt_data = def.crypt_data;
table->page_0_read = true;
}
/* Validate this single-table-tablespace with SYS_TABLES,
but do not compare the DATA_DIR flag, in case the
tablespace was relocated. */
ulint newf = def.flags;
if (newf != mod_flags) {
if (FSP_FLAGS_HAS_DATA_DIR(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR);
} else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
}
}
if (def.valid && def.id == id
&& newf == mod_flags) {
def.valid = !def.check_msg && def.id == id
&& fsp_flags_match(flags, def.flags);
if (def.valid) {
valid_tablespaces_found++;
} else {
def.valid = false;
/* Do not use this tablespace. */
fil_report_bad_tablespace(
def.filepath, def.check_msg, def.id,
@ -4254,30 +4216,18 @@ fil_open_single_table_tablespace(
remote.check_msg = fil_read_first_page(
remote.file, FALSE, &remote.flags, &remote.id,
&remote.lsn, &remote.lsn, &remote.crypt_data);
remote.valid = !remote.check_msg;
if (table) {
table->crypt_data = remote.crypt_data;
table->page_0_read = true;
}
/* Validate this single-table-tablespace with SYS_TABLES,
but do not compare the DATA_DIR flag, in case the
tablespace was relocated. */
ulint newf = remote.flags;
if (newf != mod_flags) {
if (FSP_FLAGS_HAS_DATA_DIR(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR);
} else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
}
}
if (remote.valid && remote.id == id
&& newf == mod_flags) {
/* Validate this single-table-tablespace with SYS_TABLES. */
remote.valid = !remote.check_msg && remote.id == id
&& fsp_flags_match(flags, remote.flags);
if (remote.valid) {
valid_tablespaces_found++;
} else {
remote.valid = false;
/* Do not use this linked tablespace. */
fil_report_bad_tablespace(
remote.filepath, remote.check_msg, remote.id,
@ -4291,30 +4241,19 @@ fil_open_single_table_tablespace(
dict.check_msg = fil_read_first_page(
dict.file, FALSE, &dict.flags, &dict.id,
&dict.lsn, &dict.lsn, &dict.crypt_data);
dict.valid = !dict.check_msg;
if (table) {
table->crypt_data = dict.crypt_data;
table->page_0_read = true;
}
/* Validate this single-table-tablespace with SYS_TABLES,
but do not compare the DATA_DIR flag, in case the
tablespace was relocated. */
ulint newf = dict.flags;
if (newf != mod_flags) {
if (FSP_FLAGS_HAS_DATA_DIR(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR);
} else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) {
newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE);
}
}
/* Validate this single-table-tablespace with SYS_TABLES. */
dict.valid = !dict.check_msg && dict.id == id
&& fsp_flags_match(flags, dict.flags);
if (dict.valid && dict.id == id
&& newf == mod_flags) {
if (dict.valid) {
valid_tablespaces_found++;
} else {
dict.valid = false;
/* Do not use this tablespace. */
fil_report_bad_tablespace(
dict.filepath, dict.check_msg, dict.id,
@ -4512,6 +4451,10 @@ cleanup_and_exit:
mem_free(def.filepath);
if (err == DB_SUCCESS && !srv_read_only_mode) {
fsp_flags_try_adjust(id, flags & ~FSP_FLAGS_MEM_MASK);
}
return(err);
}
#endif /* !UNIV_HOTBACKUP */
@ -4693,7 +4636,23 @@ fil_user_tablespace_restore_page(
goto out;
}
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
if (!fsp_flags_is_valid(flags)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_WARN,
"Ignoring a doublewrite copy of page "
ULINTPF ":" ULINTPF
" due to invalid flags 0x%x",
fsp->id, page_no, int(flags));
err = false;
goto out;
}
flags = cflags;
/* The flags on the page should be converted later. */
}
zip_size = fsp_flags_get_zip_size(flags);
page_size = fsp_flags_get_page_size(flags);
@ -5071,6 +5030,16 @@ will_not_choose:
}
mutex_exit(&fil_system->mutex);
#endif /* UNIV_HOTBACKUP */
/* Adjust the memory-based flags that would normally be set by
dict_tf_to_fsp_flags(). In recovery, we have no data dictionary. */
if (FSP_FLAGS_HAS_PAGE_COMPRESSION(fsp->flags)) {
fsp->flags |= page_zip_level
<< FSP_FLAGS_MEM_COMPRESSION_LEVEL;
}
remote.flags |= 1U << FSP_FLAGS_MEM_DATA_DIR;
/* We will leave atomic_writes at ATOMIC_WRITES_DEFAULT.
That will be adjusted in fil_space_for_table_exists_in_mem(). */
ibool file_space_create_success = fil_space_create(
tablename, fsp->id, fsp->flags, FIL_TABLESPACE,
fsp->crypt_data, false);
@ -5380,13 +5349,12 @@ fil_report_missing_tablespace(
name, space_id);
}
/*******************************************************************//**
Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory
/** Check if a matching tablespace exists in the InnoDB tablespace memory
cache. Note that if we have not done a crash recovery at the database startup,
there may be many tablespaces which are not yet in the memory cache.
@return TRUE if a matching tablespace exists in the memory cache */
@return whether a matching tablespace exists in the memory cache */
UNIV_INTERN
ibool
bool
fil_space_for_table_exists_in_mem(
/*==============================*/
ulint id, /*!< in: space id */
@ -5394,13 +5362,7 @@ fil_space_for_table_exists_in_mem(
fil_space_create(). Either the
standard 'dbname/tablename' format
or table->dir_path_of_temp_table */
ibool mark_space, /*!< in: in crash recovery, at database
startup we mark all spaces which have
an associated table in the InnoDB
data dictionary, so that
we can print a warning about orphaned
tablespaces */
ibool print_error_if_does_not_exist,
bool print_error_if_does_not_exist,
/*!< in: print detailed error
information to the .err log if a
matching tablespace is not found from
@ -5408,12 +5370,13 @@ fil_space_for_table_exists_in_mem(
bool adjust_space, /*!< in: whether to adjust space id
when find table space mismatch */
mem_heap_t* heap, /*!< in: heap memory */
table_id_t table_id) /*!< in: table id */
table_id_t table_id, /*!< in: table id */
ulint table_flags) /*!< in: table flags */
{
fil_space_t* fnamespace;
fil_space_t* space;
ut_ad(fil_system);
const ulint expected_flags = dict_tf_to_fsp_flags(table_flags);
mutex_enter(&fil_system->mutex);
@ -5425,42 +5388,31 @@ fil_space_for_table_exists_in_mem(
directory path from the datadir to the file */
fnamespace = fil_space_get_by_name(name);
if (space && space == fnamespace) {
/* Found */
if (mark_space) {
space->mark = TRUE;
}
mutex_exit(&fil_system->mutex);
return(TRUE);
}
/* Info from "fnamespace" comes from the ibd file itself, it can
be different from data obtained from System tables since it is
not transactional. If adjust_space is set, and the mismatching
space are between a user table and its temp table, we shall
adjust the ibd file name according to system table info */
if (adjust_space
&& space != NULL
&& row_is_mysql_tmp_table_name(space->name)
&& !row_is_mysql_tmp_table_name(name)) {
bool valid = space && !((space->flags ^ expected_flags)
& ~FSP_FLAGS_MEM_MASK);
if (!space) {
} else if (!valid || space == fnamespace) {
/* Found with the same file name, or got a flag mismatch. */
goto func_exit;
} else if (adjust_space
&& row_is_mysql_tmp_table_name(space->name)
&& !row_is_mysql_tmp_table_name(name)) {
/* Info from fnamespace comes from the ibd file
itself, it can be different from data obtained from
System tables since renaming files is not
transactional. We shall adjust the ibd file name
according to system table info. */
mutex_exit(&fil_system->mutex);
DBUG_EXECUTE_IF("ib_crash_before_adjust_fil_space",
DBUG_SUICIDE(););
if (fnamespace) {
char* tmp_name;
char* tmp_name = dict_mem_create_temporary_tablename(
heap, name, table_id);
tmp_name = dict_mem_create_temporary_tablename(
heap, name, table_id);
fil_rename_tablespace(fnamespace->name, fnamespace->id,
tmp_name, NULL);
}
fil_rename_tablespace(fnamespace->name, fnamespace->id,
tmp_name, NULL);
DBUG_EXECUTE_IF("ib_crash_after_adjust_one_fil_space",
DBUG_SUICIDE(););
@ -5473,16 +5425,12 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&fil_system->mutex);
fnamespace = fil_space_get_by_name(name);
ut_ad(space == fnamespace);
mutex_exit(&fil_system->mutex);
return(TRUE);
goto func_exit;
}
if (!print_error_if_does_not_exist) {
mutex_exit(&fil_system->mutex);
return(FALSE);
valid = false;
goto func_exit;
}
if (space == NULL) {
@ -5509,10 +5457,8 @@ error_exit:
fputs("InnoDB: Please refer to\n"
"InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
"InnoDB: for how to resolve the issue.\n", stderr);
mutex_exit(&fil_system->mutex);
return(FALSE);
valid = false;
goto func_exit;
}
if (0 != strcmp(space->name, name)) {
@ -5539,9 +5485,19 @@ error_exit:
goto error_exit;
}
func_exit:
if (valid) {
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
FSP_SPACE_FLAGS will not be written back here. */
space->flags = expected_flags;
}
mutex_exit(&fil_system->mutex);
return(FALSE);
if (valid && !srv_read_only_mode) {
fsp_flags_try_adjust(id, expected_flags & ~FSP_FLAGS_MEM_MASK);
}
return(valid);
}
/*******************************************************************//**
@ -7444,9 +7400,8 @@ fil_space_get_crypt_data(
byte *page = static_cast<byte*>(ut_align(buf, UNIV_PAGE_SIZE));
fil_read(true, space_id, 0, 0, 0, UNIV_PAGE_SIZE, page,
NULL, NULL);
ulint flags = fsp_header_get_flags(page);
ulint offset = fsp_header_get_crypt_offset(
fsp_flags_get_zip_size(flags), NULL);
fsp_header_get_zip_size(page), NULL);
space->crypt_data = fil_space_read_crypt_data(space_id, page, offset);
ut_free(buf);

3
storage/xtradb/fsp/fsp0fsp.cc

@ -663,6 +663,7 @@ fsp_header_init_fields(
ulint space_id, /*!< in: space id */
ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */
{
flags &= ~FSP_FLAGS_MEM_MASK;
ut_a(fsp_flags_is_valid(flags));
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page,
@ -713,7 +714,7 @@ fsp_header_init(
mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_SPACE_FLAGS, flags,
mlog_write_ulint(header + FSP_SPACE_FLAGS, flags & ~FSP_FLAGS_MEM_MASK,
MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);

40
storage/xtradb/include/dict0dict.ic

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB
Copyright (c) 2013, 2017, 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
@ -918,10 +918,13 @@ dict_tf_to_fsp_flags(
ulint table_flags) /*!< in: dict_table_t::flags */
{
ulint fsp_flags;
ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(
table_flags);
ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags);
ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0)
== (page_compression_level == 0));
DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure",
return(ULINT_UNDEFINED););
@ -929,30 +932,23 @@ dict_tf_to_fsp_flags(
fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0;
/* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */
fsp_flags |= table_flags & DICT_TF_MASK_ZIP_SSIZE;
fsp_flags |= table_flags & DICT_TF_MASK_ATOMIC_BLOBS;
/* In addition, tablespace flags also contain the page size. */
fsp_flags |= fsp_flags_set_page_size(fsp_flags, UNIV_PAGE_SIZE);
fsp_flags |= table_flags
& (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS);
/* The DATA_DIR flag is in a different position in fsp_flag */
fsp_flags |= DICT_TF_HAS_DATA_DIR(table_flags)
? FSP_FLAGS_MASK_DATA_DIR : 0;
fsp_flags |= FSP_FLAGS_PAGE_SSIZE();
/* In addition, tablespace flags also contain if the page
compression is used for this table. */
fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION(fsp_flags, page_compression);
if (page_compression_level) {
fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION;
}
/* In addition, tablespace flags also contain page compression level
if page compression is used for this table. */
fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(fsp_flags, page_compression_level);
ut_a(fsp_flags_is_valid(fsp_flags));
/* In addition, tablespace flags also contain flag if atomic writes
is used for this table */
fsp_flags |= FSP_FLAGS_SET_ATOMIC_WRITES(fsp_flags, atomic_writes);
if (DICT_TF_HAS_DATA_DIR(table_flags)) {
fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR;
}
ut_a(fsp_flags_is_valid(fsp_flags));
ut_a(dict_tf_verify_flags(table_flags, fsp_flags));
fsp_flags |= atomic_writes << FSP_FLAGS_MEM_ATOMIC_WRITES;
fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL;
return(fsp_flags);
}

13
storage/xtradb/include/dict0pagecompress.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013 SkySQL Ab. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -56,17 +56,6 @@ dict_table_page_compression_level(
const dict_table_t* table) /*!< in: table */
__attribute__((const));
/********************************************************************//**
Verify that dictionary flags match tablespace flags
@return true if flags match, false if not */
UNIV_INLINE
ibool
dict_tf_verify_flags(
/*=================*/
ulint table_flags, /*!< in: dict_table_t::flags */
ulint fsp_flags) /*!< in: fil_space_t::flags */
__attribute__((const));
/********************************************************************//**
Extract the atomic writes flag from table flags.
@return true if atomic writes are used, false if not used */

88
storage/xtradb/include/dict0pagecompress.ic

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013 SkySQL Ab. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -24,92 +24,6 @@ page compression and atomic writes information to dictionary.
Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
***********************************************************************/
/********************************************************************//**
Verify that dictionary flags match tablespace flags
@return true if flags match, false if not */
UNIV_INLINE
ibool
dict_tf_verify_flags(
/*=================*/
ulint table_flags, /*!< in: dict_table_t::flags */
ulint fsp_flags) /*!< in: fil_space_t::flags */
{
ulint table_unused = DICT_TF_GET_UNUSED(table_flags);
ulint compact = DICT_TF_GET_COMPACT(table_flags);
ulint ssize = DICT_TF_GET_ZIP_SSIZE(table_flags);
ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(table_flags);
ulint data_dir = DICT_TF_HAS_DATA_DIR(table_flags);
ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags);
ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags);
ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(fsp_flags);
ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags);
ulint fsp_atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(fsp_flags);
ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags);
ulint fsp_unused = FSP_FLAGS_GET_UNUSED(fsp_flags);
ulint fsp_page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags);
ulint fsp_page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags);
ulint fsp_atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(fsp_flags);
DBUG_EXECUTE_IF("dict_tf_verify_flags_failure",
return(ULINT_UNDEFINED););
ut_a(!table_unused);
ut_a(!fsp_unused);
ut_a(page_ssize == 0 || page_ssize != 0); /* silence compiler */
ut_a(compact == 0 || compact == 1); /* silence compiler */
ut_a(data_dir == 0 || data_dir == 1); /* silence compiler */
ut_a(post_antelope == 0 || post_antelope == 1); /* silence compiler */
if (ssize != zip_ssize) {
fprintf(stderr,
"InnoDB: Error: table flags has zip_ssize %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has zip_ssize %ld\n",
ssize, zip_ssize);
return (FALSE);
}
if (atomic_blobs != fsp_atomic_blobs) {
fprintf(stderr,
"InnoDB: Error: table flags has atomic_blobs %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has atomic_blobs %ld\n",
atomic_blobs, fsp_atomic_blobs);
return (FALSE);
}
if (page_compression != fsp_page_compression) {
fprintf(stderr,
"InnoDB: Error: table flags has page_compression %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file ahas page_compression %ld\n",
page_compression, fsp_page_compression);
return (FALSE);
}
if (page_compression_level != fsp_page_compression_level) {
fprintf(stderr,
"InnoDB: Error: table flags has page_compression_level %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has page_compression_level %ld\n",
page_compression_level, fsp_page_compression_level);
return (FALSE);
}
if (atomic_writes != fsp_atomic_writes) {
fprintf(stderr,
"InnoDB: Error: table flags has atomic writes %ld"
" in the data dictionary\n"
"InnoDB: but the flags in file has atomic_writes %ld\n",
atomic_writes, fsp_atomic_writes);
return (FALSE);
}
return(TRUE);
}
/********************************************************************//**
Extract the page compression level from dict_table_t::flags.
These flags are in memory, so assert that they are valid.

41
storage/xtradb/include/fil0fil.h

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@ -45,7 +45,6 @@ Created 10/25/1995 Heikki Tuuri
// Forward declaration
struct trx_t;
struct fil_space_t;
typedef std::list<const char*> space_name_list_t;
@ -264,10 +263,6 @@ struct fil_space_t {
an insert buffer merge request for a
page because it actually was for the
previous incarnation of the space */
ibool mark; /*!< this is set to TRUE at database startup if
the space corresponds to a table in the InnoDB
data dictionary; so we can print a warning of
orphaned tablespaces */
ibool stop_ios;/*!< TRUE if we want to rename the
.ibd file of tablespace and want to
stop temporarily posting of new i/o
@ -296,7 +291,8 @@ struct fil_space_t {
/*!< recovered tablespace size in pages;
0 if no size change was read from the redo log,
or if the size change was implemented */
ulint flags; /*!< tablespace flags; see
ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
see fsp0fsp.h,
fsp_flags_is_valid(),
fsp_flags_get_zip_size() */
ulint n_reserved_extents;
@ -449,6 +445,7 @@ fil_node_create(
ibool is_raw) /*!< in: TRUE if a raw device or
a raw disk partition */
MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_LOG_ARCHIVE
/****************************************************************//**
Drops files from the start of a file space, so that its size is cut by
@ -620,7 +617,7 @@ fil_read_first_page(
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
ulint* flags, /*!< out: FSP_SPACE_FLAGS */
ulint* space_id, /*!< out: tablespace ID */
lsn_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
@ -832,6 +829,14 @@ fil_create_new_single_table_tablespace(
ulint key_id) /*!< in: encryption key_id */
__attribute__((nonnull, warn_unused_result));
#ifndef UNIV_HOTBACKUP
/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations.
(Typically when upgrading from MariaDB 10.1.0..10.1.20.)
@param[in] space_id tablespace ID
@param[in] flags desired tablespace flags */
UNIV_INTERN
void
fsp_flags_try_adjust(ulint space_id, ulint flags);
/********************************************************************//**
Tries to open a single-table tablespace and optionally checks the space id is
right in it. If does not succeed, prints an error message to the .err log. This
@ -860,7 +865,7 @@ fil_open_single_table_tablespace(
bool validate, /*!< in: Do we validate tablespace? */
bool fix_dict, /*!< in: Can we fix the dictionary? */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
ulint flags, /*!< in: expected FSP_SPACE_FLAGS */
const char* tablename, /*!< in: table name in the
databasename/tablename format */
const char* filepath, /*!< in: tablespace filepath */
@ -901,25 +906,18 @@ fil_tablespace_exists_in_mem(
/*=========================*/
ulint id); /*!< in: space id */
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory
/** Check if a matching tablespace exists in the InnoDB tablespace memory
cache. Note that if we have not done a crash recovery at the database startup,
there may be many tablespaces which are not yet in the memory cache.
@return TRUE if a matching tablespace exists in the memory cache */
@return whether a matching tablespace exists in the memory cache */
UNIV_INTERN
ibool
bool
fil_space_for_table_exists_in_mem(
/*==============================*/
ulint id, /*!< in: space id */
const char* name, /*!< in: table name in the standard
'databasename/tablename' format */
ibool mark_space, /*!< in: in crash recovery, at database
startup we mark all spaces which have
an associated table in the InnoDB
data dictionary, so that
we can print a warning about orphaned
tablespaces */
ibool print_error_if_does_not_exist,
bool print_error_if_does_not_exist,
/*!< in: print detailed error
information to the .err log if a
matching tablespace is not found from
@ -927,7 +925,8 @@ fil_space_for_table_exists_in_mem(
bool adjust_space, /*!< in: whether to adjust space id
when find table space mismatch */
mem_heap_t* heap, /*!< in: heap memory */
table_id_t table_id); /*!< in: table id */
table_id_t table_id, /*!< in: table id */
ulint table_flags); /*!< in: table flags */
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
Extends all tablespaces to the size stored in the space header. During the

13
storage/xtradb/include/fil0pagecompress.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2016 MariaDB Corporation. All Rights Reserved.
Copyright (C) 2013, 2017 MariaDB Corporation. All Rights Reserved.
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
@ -44,20 +44,11 @@ Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */
UNIV_INLINE
ibool
bool
fil_space_is_page_compressed(
/*=========================*/
ulint id); /*!< in: space id */
/*******************************************************************//**
Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */
UNIV_INTERN
ibool
fil_space_get_page_compressed(
/*=========================*/
fil_space_t* space); /*!< in: space id */
/*******************************************************************//**
Returns the atomic writes flag of the space, or false if the space
is not using atomic writes. The tablespace must be cached in the memory cache.
@return atomic write table option value */

437
storage/xtradb/include/fsp0fsp.h

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -51,28 +51,67 @@ to the two Barracuda row formats COMPRESSED and DYNAMIC. */
#define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1
/** Number of flag bits used to indicate the tablespace page size */
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
/** Width of the DATA_DIR flag. This flag indicates that the tablespace
is found in a remote location, not the default data directory. */
#define FSP_FLAGS_WIDTH_DATA_DIR 1
/** Number of flag bits used to indicate the page compression and compression level */
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL 4
/** Number of reserved bits */
#define FSP_FLAGS_WIDTH_RESERVED 6
/** Number of flag bits used to indicate the page compression */
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1
/** Number of flag bits used to indicate atomic writes for this tablespace */
#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 2
/** Width of all the currently known tablespace flags */
/** Width of all the currently known persistent tablespace flags */
#define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \
+ FSP_FLAGS_WIDTH_ZIP_SSIZE \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_PAGE_SSIZE \
+ FSP_FLAGS_WIDTH_DATA_DIR \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL \
+ FSP_FLAGS_WIDTH_ATOMIC_WRITES )
/** A mask of all the known/used bits in tablespace flags */
#define FSP_FLAGS_MASK (~(~0 << FSP_FLAGS_WIDTH))
+ FSP_FLAGS_WIDTH_RESERVED \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION)
/** A mask of all the known/used bits in FSP_SPACE_FLAGS */
#define FSP_FLAGS_MASK (~(~0U << FSP_FLAGS_WIDTH))
/* FSP_SPACE_FLAGS position and name in MySQL 5.6/MariaDB 10.0 or older
and MariaDB 10.1.20 or older MariaDB 10.1 and in MariaDB 10.1.21
or newer.
MySQL 5.6 MariaDB 10.1.x MariaDB 10.1.21
====================================================================
Below flags in same offset
====================================================================
0: POST_ANTELOPE 0:POST_ANTELOPE 0: POST_ANTELOPE
1..4: ZIP_SSIZE(0..5) 1..4:ZIP_SSIZE(0..5) 1..4: ZIP_SSIZE(0..5)
(NOTE: bit 4 is always 0)
5: ATOMIC_BLOBS 5:ATOMIC_BLOBS 5: ATOMIC_BLOBS
=====================================================================
Below note the order difference:
=====================================================================
6..9: PAGE_SSIZE(3..7) 6: COMPRESSION 6..9: PAGE_SSIZE(3..7)
10: DATA_DIR 7..10: COMP_LEVEL(0..9) 10: RESERVED (5.6 DATA_DIR)
=====================================================================
The flags below were in incorrect position in MariaDB 10.1,
or have been introduced in MySQL 5.7 or 8.0:
=====================================================================
11: UNUSED 11..12:ATOMIC_WRITES 11: RESERVED (5.7 SHARED)
12: RESERVED (5.7 TEMPORARY)
13..15:PAGE_SSIZE(3..7) 13: RESERVED (5.7 ENCRYPTION)
14: RESERVED (8.0 SDI)
15: RESERVED
16: PAGE_SSIZE_msb(0) 16: COMPRESSION
17: DATA_DIR 17: UNUSED
18: UNUSED
=====================================================================
The flags below only exist in fil_space_t::flags, not in FSP_SPACE_FLAGS:
=====================================================================
25: DATA_DIR
26..27: ATOMIC_WRITES
28..31: COMPRESSION_LEVEL
*/
/** A mask of the memory-only flags in fil_space_t::flags */
#define FSP_FLAGS_MEM_MASK (~0U << FSP_FLAGS_MEM_DATA_DIR)
/** Zero relative shift position of the DATA_DIR flag */
#define FSP_FLAGS_MEM_DATA_DIR 25
/** Zero relative shift position of the ATOMIC_WRITES field */
#define FSP_FLAGS_MEM_ATOMIC_WRITES 26
/** Zero relative shift position of the COMPRESSION_LEVEL field */
#define FSP_FLAGS_MEM_COMPRESSION_LEVEL 28
/** Zero relative shift position of the POST_ANTELOPE field */
#define FSP_FLAGS_POS_POST_ANTELOPE 0
@ -82,29 +121,16 @@ is found in a remote location, not the default data directory. */
/** Zero relative shift position of the ATOMIC_BLOBS field */
#define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \
+ FSP_FLAGS_WIDTH_ZIP_SSIZE)
/** Note that these need to be before the page size to be compatible with
dictionary */
/** Zero relative shift position of the PAGE_COMPRESSION field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL (FSP_FLAGS_POS_PAGE_COMPRESSION \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION)
/** Zero relative shift position of the ATOMIC_WRITES field */
#define FSP_FLAGS_POS_ATOMIC_WRITES (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL \
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)
/** Zero relative shift position of the PAGE_SSIZE field */
#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_WRITES \
+ FSP_FLAGS_WIDTH_ATOMIC_WRITES)
/** Zero relative shift position of the start of the DATA DIR bits */
#define FSP_FLAGS_POS_DATA_DIR (FSP_FLAGS_POS_PAGE_SSIZE \
+ FSP_FLAGS_WIDTH_PAGE_SSIZE)
#define FSP_FLAGS_POS_DATA_DIR_ORACLE (FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS \
/** Zero relative shift position of the start of the PAGE_SSIZE bits */
#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
/** Zero relative shift position of the start of the RESERVED bits
these are only used in MySQL 5.7 and used for compatibility. */
#define FSP_FLAGS_POS_RESERVED (FSP_FLAGS_POS_PAGE_SSIZE \
+ FSP_FLAGS_WIDTH_PAGE_SSIZE)
/** Zero relative shift position of the start of the UNUSED bits */
#define FSP_FLAGS_POS_UNUSED (FSP_FLAGS_POS_DATA_DIR\
+ FSP_FLAGS_WIDTH_DATA_DIR)
/** Zero relative shift position of the PAGE_COMPRESSION field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_RESERVED \
+ FSP_FLAGS_WIDTH_RESERVED)
/** Bit mask of the POST_ANTELOPE field */
#define FSP_FLAGS_MASK_POST_ANTELOPE \
@ -122,26 +148,23 @@ dictionary */
#define FSP_FLAGS_MASK_PAGE_SSIZE \
((~(~0U << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** Bit mask of the DATA_DIR field */
#define FSP_FLAGS_MASK_DATA_DIR \
((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \
<< FSP_FLAGS_POS_DATA_DIR)
/** Bit mask of the DATA_DIR field */
#define FSP_FLAGS_MASK_DATA_DIR_ORACLE \
((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \
<< FSP_FLAGS_POS_DATA_DIR_ORACLE)
/** Bit mask of the RESERVED1 field */
#define FSP_FLAGS_MASK_RESERVED \
((~(~0U << FSP_FLAGS_WIDTH_RESERVED)) \
<< FSP_FLAGS_POS_RESERVED)
/** Bit mask of the PAGE_COMPRESSION field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION \
#define FSP_FLAGS_MASK_PAGE_COMPRESSION \
((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \
<< FSP_FLAGS_POS_PAGE_COMPRESSION)
/** Bit mask of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL \
((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)) \
<< FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)
/** Bit mask of the ATOMIC_WRITES field */
#define FSP_FLAGS_MASK_ATOMIC_WRITES \
((~(~0U << FSP_FLAGS_WIDTH_ATOMIC_WRITES)) \
<< FSP_FLAGS_POS_ATOMIC_WRITES)
/** Bit mask of the in-memory ATOMIC_WRITES field */
#define FSP_FLAGS_MASK_MEM_ATOMIC_WRITES \
(3U << FSP_FLAGS_MEM_ATOMIC_WRITES)
/** Bit mask of the in-memory COMPRESSION_LEVEL field */
#define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \
(15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL)
/** Return the value of the POST_ANTELOPE field */
#define FSP_FLAGS_GET_POST_ANTELOPE(flags) \
((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \
@ -158,48 +181,78 @@ dictionary */
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
>> FSP_FLAGS_POS_PAGE_SSIZE)
/** Return the value of the DATA_DIR field */
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
((flags & FSP_FLAGS_MASK_DATA_DIR) \
>> FSP_FLAGS_POS_DATA_DIR)
#define FSP_FLAGS_HAS_DATA_DIR_ORACLE(flags) \
((flags & FSP_FLAGS_MASK_DATA_DIR_ORACLE) \
>> FSP_FLAGS_POS_DATA_DIR_ORACLE)
/** @return the RESERVED flags */
#define FSP_FLAGS_GET_RESERVED(flags) \
((flags & FSP_FLAGS_MASK_RESERVED) \
>> FSP_FLAGS_POS_RESERVED)
/** @return the PAGE_COMPRESSION flag */
#define FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION)
/** Return the contents of the UNUSED bits */
#define FSP_FLAGS_GET_UNUSED(flags) \
(flags >> FSP_FLAGS_POS_UNUSED)
/** @return the PAGE_SSIZE flags for the current innodb_page_size */
#define FSP_FLAGS_PAGE_SSIZE() \
((UNIV_PAGE_SIZE == UNIV_PAGE_SIZE_ORIG) ? \
0 : (UNIV_PAGE_SIZE_SHIFT - UNIV_ZIP_SIZE_SHIFT_MIN + 1) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** @return the value of the DATA_DIR field */
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
(flags & 1U << FSP_FLAGS_MEM_DATA_DIR)
/** @return the COMPRESSION_LEVEL field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \
((flags & FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL) \
>> FSP_FLAGS_MEM_COMPRESSION_LEVEL)
/** @return the ATOMIC_WRITES field */
#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \
((flags & FSP_FLAGS_MASK_MEM_ATOMIC_WRITES) \
>> FSP_FLAGS_MEM_ATOMIC_WRITES)
/* Compatibility macros for MariaDB 10.1.20 or older 10.1 see
table above. */
/** Zero relative shift position of the PAGE_COMPRESSION field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 \
(FSP_FLAGS_POS_ATOMIC_BLOBS \
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 \
(FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 + 1)
/** Zero relative shift position of the ATOMIC_WRITES field */
#define FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 \
(FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 + 4)
/** Zero relative shift position of the PAGE_SSIZE field */
#define FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101 \
(FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 + 2)
/** Bit mask of the PAGE_COMPRESSION field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101 \
(1U << FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101)
/** Bit mask of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101 \
(15U << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101)
/** Bit mask of the ATOMIC_WRITES field */
#define FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101 \
(3U << FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101)
/** Bit mask of the PAGE_SSIZE field */
#define FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101 \
(15U << FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101)
/** Return the value of the PAGE_COMPRESSION field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION)
#define FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101)
/** Return the value of the PAGE_COMPRESSION_LEVEL field */
#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)
/** Return the value of the ATOMIC_WRITES field */
#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \
((flags & FSP_FLAGS_MASK_ATOMIC_WRITES) \
>> FSP_FLAGS_POS_ATOMIC_WRITES)
/** Set a PAGE_SSIZE into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize) \
(flags | (ssize << FSP_FLAGS_POS_PAGE_SSIZE))
/** Set a PAGE_COMPRESSION into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_PAGE_COMPRESSION(flags, compression) \
(flags | (compression << FSP_FLAGS_POS_PAGE_COMPRESSION))
/** Set a PAGE_COMPRESSION_LEVEL into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, level) \
(flags | (level << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL))
/** Set a ATOMIC_WRITES into the correct bits in a given
tablespace flags. */
#define FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomics) \
(flags | (atomics << FSP_FLAGS_POS_ATOMIC_WRITES))
#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101)
/** Return the value of the PAGE_SSIZE field */
#define FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags) \
((flags & FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101) \
>> FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101)
/* @} */
@ -733,19 +786,193 @@ fseg_print(
mtr_t* mtr); /*!< in/out: mini-transaction */
#endif /* UNIV_BTR_PRINT */
/********************************************************************//**
Validate and return the tablespace flags, which are stored in the
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
have a file format number plus the DICT_TF_COMPACT bit set.
@return true if check ok */
/** Validate the tablespace flags, which are stored in the
tablespace header at offset FSP_SPACE_FLAGS.
@param[in] flags the contents of FSP_SPACE_FLAGS
@return whether the flags are correct (not in the buggy 10.1) format */
MY_ATTRIBUTE((warn_unused_result, const))
UNIV_INLINE
bool
fsp_flags_is_valid(
/*===============*/
ulint flags) /*!< in: tablespace flags */
MY_ATTRIBUTE((warn_unused_result, const));
fsp_flags_is_valid(ulint flags)
{
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
return(false););
if (flags == 0) {
return(true);
}
if (flags & ~FSP_FLAGS_MASK) {
return(false);
}
if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS))
== FSP_FLAGS_MASK_ATOMIC_BLOBS) {
/* If the "atomic blobs" flag (indicating
ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag
is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag
must also be set. */
return(false);
}
/* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag
of MySQL 5.6 and MariaDB 10.0, which we ignore.
In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20,
bits 10..14 would be nonzero 0bsssaa where sss is
nonzero PAGE_SSIZE (3, 4, 6, or 7)
and aa is ATOMIC_WRITES (not 0b11). */
if (FSP_FLAGS_GET_RESERVED(flags) & ~1) {
return(false);
}
const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) {
/* the page_size is not between 4k and 64k;
16k should be encoded as 0, not 5 */
return(false);
}
const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
if (zssize == 0) {
/* not ROW_FORMAT=COMPRESSED */
} else if (zssize > (ssize ? ssize : 5)) {
/* invalid KEY_BLOCK_SIZE */
return(false);
} else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE
| FSP_FLAGS_MASK_ATOMIC_BLOBS)) {
/* both these flags should be set for
ROW_FORMAT=COMPRESSED */
return(false);
}
return(true);
}
/** Convert FSP_SPACE_FLAGS from the buggy MariaDB 10.1.0..10.1.20 format.
@param[in] flags the contents of FSP_SPACE_FLAGS
@return the flags corrected from the buggy MariaDB 10.1 format
@retval ULINT_UNDEFINED if the flags are not in the buggy 10.1 format */
MY_ATTRIBUTE((warn_unused_result, const))
UNIV_INLINE
ulint
fsp_flags_convert_from_101(ulint flags)
{
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
return(ULINT_UNDEFINED););
if (flags == 0) {
return(flags);
}
if (flags >> 18) {
/* The most significant FSP_SPACE_FLAGS bit that was ever set
by MariaDB 10.1.0 to 10.1.20 was bit 17 (misplaced DATA_DIR flag).
The flags must be less than 1<<18 in order to be valid. */
return(ULINT_UNDEFINED);
}
if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS))
== FSP_FLAGS_MASK_ATOMIC_BLOBS) {
/* If the "atomic blobs" flag (indicating
ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag
is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag
must also be set. */
return(ULINT_UNDEFINED);
}
/* Bits 6..10 denote compression in MariaDB 10.1.0 to 10.1.20.
They must be either 0b00000 or 0b00011 through 0b10011.
In correct versions, these bits would be
0bd0sss where d is the DATA_DIR flag (garbage bit) and
sss is the PAGE_SSIZE (3, 4, 6, or 7).
NOTE: MariaDB 10.1.0 to 10.1.20 can misinterpret
uncompressed data files with innodb_page_size=4k or 64k as
compressed innodb_page_size=16k files. Below is an exhaustive
state space analysis.
-0by1zzz: impossible (the bit 4 must be clean; see above)
-0b101xx: DATA_DIR, innodb_page_size>4k: invalid (COMPRESSION_LEVEL>9)
+0bx0011: innodb_page_size=4k:
!!! Misinterpreted as COMPRESSION_LEVEL=9 or 1, COMPRESSION=1.
-0bx0010: impossible, because sss must be 0b011 or 0b1xx
-0bx0001: impossible, because sss must be 0b011 or 0b1xx
-0b10000: DATA_DIR, innodb_page_size=16:
invalid (COMPRESSION_LEVEL=8 but COMPRESSION=0)
+0b00111: no DATA_DIR, innodb_page_size=64k:
!!! Misinterpreted as COMPRESSION_LEVEL=3, COMPRESSION=1.
-0b00101: impossible, because sss must be 0 for 16k, not 0b101
-0b001x0: no DATA_DIR, innodb_page_size=32k or 8k:
invalid (COMPRESSION_LEVEL=3 but COMPRESSION=0)
+0b00000: innodb_page_size=16k (looks like COMPRESSION=0)
??? Could actually be compressed; see PAGE_SSIZE below */
const ulint level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101(
flags);
if (FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) != (level != 0)
|| level > 9) {
/* The compression flags are not in the buggy MariaDB
10.1 format. */
return(ULINT_UNDEFINED);
}
if (!(~flags & FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101)) {
/* The ATOMIC_WRITES flags cannot be 0b11.
(The bits 11..12 should actually never be 0b11,
because in MySQL they would be SHARED|TEMPORARY.) */
return(ULINT_UNDEFINED);
}
/* Bits 13..16 are the wrong position for PAGE_SSIZE, and they
should contain one of the values 3,4,6,7, that is, be of the form
0b0011 or 0b01xx (except 0b0110).
In correct versions, these bits should be 0bc0se
where c is the MariaDB COMPRESSED flag
and e is the MySQL 5.7 ENCRYPTION flag
and s is the MySQL 8.0 SDI flag. MariaDB can only support s=0, e=0.
Compressed innodb_page_size=16k tables with correct FSP_SPACE_FLAGS
will be properly rejected by older MariaDB 10.1.x because they
would read as PAGE_SSIZE>=8 which is not valid. */
const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags);
if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) {
/* the page_size is not between 4k and 64k;
16k should be encoded as 0, not 5 */
return(ULINT_UNDEFINED);
}
const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
if (zssize == 0) {
/* not ROW_FORMAT=COMPRESSED */
} else if (zssize > (ssize ? ssize : 5)) {
/* invalid KEY_BLOCK_SIZE */
return(ULINT_UNDEFINED);
} else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE
| FSP_FLAGS_MASK_ATOMIC_BLOBS)) {
/* both these flags should be set for
ROW_FORMAT=COMPRESSED */
return(ULINT_UNDEFINED);
}
flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE
| FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags)
<< FSP_FLAGS_POS_PAGE_COMPRESSION);
ut_ad(fsp_flags_is_valid(flags));
return(flags);
}
/** Compare tablespace flags.
@param[in] expected expected flags from dict_tf_to_fsp_flags()
@param[in] actual flags read from FSP_SPACE_FLAGS
@return whether the flags match */
MY_ATTRIBUTE((warn_unused_result))
UNIV_INLINE
bool
fsp_flags_match(ulint expected, ulint actual)
{
expected &= ~FSP_FLAGS_MEM_MASK;
ut_ad(fsp_flags_is_valid(expected));
if (actual == expected) {
return(true);
}
actual = fsp_flags_convert_from_101(actual);
return(actual == expected);
}
/********************************************************************//**
Determine if the tablespace is compressed from dict_table_t::flags.
@return TRUE if compressed, FALSE if not compressed */

153
storage/xtradb/include/fsp0fsp.ic

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
Copyright (c) 2013, 2017, 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
@ -46,107 +46,6 @@ fsp_descr_page(
return((page_no & (zip_size - 1)) == FSP_XDES_OFFSET);
}
/********************************************************************//**
Validate and return the tablespace flags, which are stored in the
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
have a file format number plus the DICT_TF_COMPACT bit set.
@return true if check ok */
UNIV_INLINE
bool
fsp_flags_is_valid(
/*===============*/
ulint flags) /*!< in: tablespace flags */
{
ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(flags);
ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
ulint unused = FSP_FLAGS_GET_UNUSED(flags);
ulint page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags);
ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags);
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false););
/* fsp_flags is zero unless atomic_blobs is set. */
/* Make sure there are no bits that we do not know about. */
if (unused != 0 || flags == 1) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted unused %lu\n",
flags, unused);
return(false);
} else if (post_antelope) {
/* The Antelope row formats REDUNDANT and COMPACT did
not use tablespace flags, so this flag and the entire
4-byte field is zero for Antelope row formats. */
if (!atomic_blobs) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_blobs %lu\n",
flags, atomic_blobs);
return(false);
}
}
if (!atomic_blobs) {
/* Barracuda row formats COMPRESSED and DYNAMIC build on
the page structure introduced for the COMPACT row format
by allowing long fields to be broken into prefix and
externally stored parts. */
if (post_antelope || zip_ssize != 0) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu atomic_blobs %lu\n",
flags, zip_ssize, atomic_blobs);
return(false);
}
} else if (!post_antelope || zip_ssize > PAGE_ZIP_SSIZE_MAX) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu max %d\n",
flags, zip_ssize, PAGE_ZIP_SSIZE_MAX);
return(false);
} else if (page_ssize > UNIV_PAGE_SSIZE_MAX) {
/* The page size field can be used for any row type, or it may
be zero for an original 16k page size.
Validate the page shift size is within allowed range. */
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu\n",
flags, page_ssize, UNIV_PAGE_SSIZE_MAX);
return(false);
} else if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_ORIG && !page_ssize) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu:%d\n",
flags, page_ssize, UNIV_PAGE_SIZE, UNIV_PAGE_SIZE_ORIG);
return(false);
}
#if UNIV_FORMAT_MAX != UNIV_FORMAT_B
# error "UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations."
#endif
/* Page compression level requires page compression and atomic blobs
to be set */
if (page_compression_level || page_compression) {
if (!page_compression || !atomic_blobs) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_compression %lu\n"
"InnoDB: Error: page_compression_level %lu atomic_blobs %lu\n",
flags, page_compression, page_compression_level, atomic_blobs);
return(false);
}
}
if (atomic_writes > ATOMIC_WRITES_OFF) {
fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_writes %lu\n",
flags, atomic_writes);
return (false);
}
/* The DATA_DIR field can be used for any row type so there is
nothing here to validate. */
return(true);
}
/********************************************************************//**
Determine if the tablespace is compressed from dict_table_t::flags.
@return TRUE if compressed, FALSE if not compressed */
@ -191,10 +90,10 @@ UNIV_INLINE
ulint
fsp_flags_get_page_size(
/*====================*/
ulint flags) /*!< in: tablespace flags */
ulint flags) /*!< in: tablespace flags */
{
ulint page_size = 0;
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
ulint page_size = 0;
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
/* Convert from a 'log2 minus 9' to a page size in bytes. */
if (UNIV_UNLIKELY(ssize)) {
@ -211,50 +110,6 @@ fsp_flags_get_page_size(
}
#ifndef UNIV_INNOCHECKSUM
/********************************************************************//**
Add the page size to the tablespace flags.
@return tablespace flags after page size is added */
UNIV_INLINE
ulint
fsp_flags_set_page_size(
/*====================*/
ulint flags, /*!< in: tablespace flags */
ulint page_size) /*!< in: page size in bytes */
{
ulint ssize = 0;
ulint shift;
/* Page size should be > UNIV_PAGE_SIZE_MIN */
ut_ad(page_size >= UNIV_PAGE_SIZE_MIN);
ut_ad(page_size <= UNIV_PAGE_SIZE_MAX);
if (page_size == UNIV_PAGE_SIZE_ORIG) {
ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags));
return(flags);
}
for (shift = UNIV_PAGE_SIZE_SHIFT_MAX;
shift >= UNIV_PAGE_SIZE_SHIFT_MIN;
shift--) {
ulint mask = (1 << shift);
if (page_size & mask) {
ut_ad(!(page_size & ~mask));
ssize = shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1;
break;
}
}
ut_ad(ssize);
ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX);
flags = FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize);
ut_ad(fsp_flags_is_valid(flags));
return(flags);
}
/********************************************************************//**
Calculates the descriptor index within a descriptor page.
@return descriptor index */

11
storage/xtradb/include/fsp0pagecompress.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -47,15 +47,6 @@ fsp_header_get_compression_level(
/*=============================*/
const page_t* page); /*!< in: first page of a tablespace */
/********************************************************************//**
Determine if the tablespace is page compressed from dict_table_t::flags.
@return TRUE if page compressed, FALSE if not compressed */
UNIV_INLINE
ibool
fsp_flags_is_page_compressed(
/*=========================*/
ulint flags); /*!< in: tablespace flags */
/********************************************************************//**
Extract the page compression level from tablespace flags.
A tablespace has only one physical page compression level

28
storage/xtradb/include/fsp0pagecompress.ic

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@ -25,18 +25,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@mariadb.com
***********************************************************************/
/********************************************************************//**
Determine if the tablespace is page compressed from dict_table_t::flags.
@return TRUE if page compressed, FALSE if not page compressed */
UNIV_INLINE
ibool
fsp_flags_is_page_compressed(
/*=========================*/
ulint flags) /*!< in: tablespace flags */
{
return(FSP_FLAGS_GET_PAGE_COMPRESSION(flags));
}
/********************************************************************//**
Determine the tablespace is page compression level from dict_table_t::flags.
@return page compression level or 0 if not compressed*/
@ -125,21 +113,15 @@ Extract the page compression from space.
@return true if space is page compressed, false if space is not found
or space is not page compressed. */
UNIV_INLINE
ibool
bool
fil_space_is_page_compressed(
/*=========================*/
ulint id) /*!< in: space id */
{
ulint flags;
flags = fil_space_get_flags(id);
if (flags && flags != ULINT_UNDEFINED) {
return(fsp_flags_is_page_compressed(flags));
}
ulint flags = fil_space_get_flags(id);
return(0);
return(flags != ULINT_UNDEFINED
&& FSP_FLAGS_HAS_PAGE_COMPRESSION(flags));
}
#endif /* UNIV_INNOCHECKSUM */

94
storage/xtradb/row/row0import.cc

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, MariaDB Corporation.
Copyright (c) 2015, 2017, 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
@ -371,8 +371,7 @@ public:
m_space(ULINT_UNDEFINED),
m_xdes(),
m_xdes_page_no(ULINT_UNDEFINED),
m_space_flags(ULINT_UNDEFINED),
m_table_flags(ULINT_UNDEFINED) UNIV_NOTHROW { }
m_space_flags(ULINT_UNDEFINED) UNIV_NOTHROW { }
/**
Free any extent descriptor instance */
@ -535,10 +534,6 @@ protected:
/** Flags value read from the header page */
ulint m_space_flags;
/** Derived from m_space_flags and row format type, the row format
type is determined from the page header. */
ulint m_table_flags;
};
/** Determine the page size to use for traversing the tablespace
@ -553,6 +548,19 @@ AbstractCallback::init(
const page_t* page = block->frame;
m_space_flags = fsp_header_get_flags(page);
if (!fsp_flags_is_valid(m_space_flags)) {
ulint cflags = fsp_flags_convert_from_101(m_space_flags);
if (cflags == ULINT_UNDEFINED) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Invalid FSP_SPACE_FLAGS=0x%x",
int(m_space_flags));
return(DB_CORRUPTION);
}
m_space_flags = cflags;
}
/* Clear the DATA_DIR flag, which is basically garbage. */
m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED);
/* Since we don't know whether it is a compressed table
or not, the data is always read into the block->frame. */
@ -640,46 +648,6 @@ struct FetchIndexRootPages : public AbstractCallback {
return(m_space);
}
/**
Check if the .ibd file row format is the same as the table's.
@param ibd_table_flags - determined from space and page.
@return DB_SUCCESS or error code. */
dberr_t check_row_format(ulint ibd_table_flags) UNIV_NOTHROW
{
dberr_t err;
rec_format_t ibd_rec_format;
rec_format_t table_rec_format;
if (!dict_tf_is_valid(ibd_table_flags)) {
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
".ibd file has invlad table flags: %lx",
ibd_table_flags);
return(DB_CORRUPTION);
}
ibd_rec_format = dict_tf_get_rec_format(ibd_table_flags);
table_rec_format = dict_tf_get_rec_format(m_table->flags);
if (table_rec_format != ibd_rec_format) {
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
"Table has %s row format, .ibd "
"file has %s row format.",
dict_tf_to_row_format_string(m_table->flags),
dict_tf_to_row_format_string(ibd_table_flags));
err = DB_CORRUPTION;
} else {
err = DB_SUCCESS;
}
return(err);
}
/**
Called for each block as it is read from the file.
@param offset - physical offset in the file
@ -743,12 +711,17 @@ FetchIndexRootPages::operator() (
m_indexes.push_back(Index(id, page_no));
if (m_indexes.size() == 1) {
m_table_flags = dict_sys_tables_type_to_tf(
m_space_flags,
page_is_comp(page) ? DICT_N_COLS_COMPACT : 0);
err = check_row_format(m_table_flags);
/* Check that the tablespace flags match the table flags. */
ulint expected = dict_tf_to_fsp_flags(m_table->flags);
if (!fsp_flags_match(expected, m_space_flags)) {
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
"Expected FSP_SPACE_FLAGS=0x%x, .ibd "
"file contains 0x%x.",
unsigned(expected),
unsigned(m_space_flags));
return(DB_CORRUPTION);
}
}
}
@ -1968,21 +1941,14 @@ PageConverter::update_header(
"- ignored");
}
ulint space_flags = fsp_header_get_flags(get_frame(block));
if (!fsp_flags_is_valid(space_flags)) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Unsupported tablespace format %lu",
(ulong) space_flags);
return(DB_UNSUPPORTED);
}
mach_write_to_8(
get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
m_current_lsn);
/* Write back the adjusted flags. */
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ get_frame(block), m_space_flags);
/* Write space_id to the tablespace header, page 0. */
mach_write_to_4(
get_frame(block) + FSP_HEADER_OFFSET + FSP_SPACE_ID,

11
storage/xtradb/row/row0mysql.cc

@ -4362,6 +4362,7 @@ row_drop_table_for_mysql(
switch (err) {
ibool is_temp;
ulint table_flags;
case DB_SUCCESS:
/* Clone the name, in case it has been allocated
@ -4370,6 +4371,7 @@ row_drop_table_for_mysql(
space_id = table->space;
ibd_file_missing = table->ibd_file_missing;
table_flags = table->flags;
is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY);
/* If there is a temp path then the temp flag is set.
@ -4385,9 +4387,9 @@ row_drop_table_for_mysql(
}
/* We do not allow temporary tables with a remote path. */
ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table->flags)));
ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table_flags)));
if (space_id && DICT_TF_HAS_DATA_DIR(table->flags)) {
if (space_id && DICT_TF_HAS_DATA_DIR(table_flags)) {
dict_get_and_save_data_dir_path(table, true);
ut_a(table->data_dir_path);
@ -4453,8 +4455,9 @@ row_drop_table_for_mysql(
if (err == DB_SUCCESS && space_id > TRX_SYS_SPACE) {
if (!is_temp
&& !fil_space_for_table_exists_in_mem(
space_id, tablename, FALSE,
print_msg, false, NULL, 0)) {
space_id, tablename,
print_msg, false, NULL, 0,
table_flags)) {
/* This might happen if we are dropping a
discarded tablespace */
err = DB_SUCCESS;

18
storage/xtradb/srv/srv0start.cc

@ -703,8 +703,7 @@ create_log_files(
sprintf(logfilename + dirnamelen, "ib_logfile%u", INIT_LOG_FILE0);
fil_space_create(
logfilename, SRV_LOG_SPACE_FIRST_ID,
fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
logfilename, SRV_LOG_SPACE_FIRST_ID, 0,
FIL_LOG,
NULL /* no encryption yet */,
true /* this is create */);
@ -1193,7 +1192,7 @@ check_first_page:
crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
}
flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE);
flags = FSP_FLAGS_PAGE_SSIZE();
fil_space_create(name, 0, flags, FIL_TABLESPACE,
crypt_data, (*create_new_db) == true);
@ -1341,7 +1340,7 @@ srv_undo_tablespace_open(
fil_set_max_space_id_if_bigger(space);
/* Set the compressed page size to 0 (non-compressed) */
flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE);
flags = FSP_FLAGS_PAGE_SSIZE();
fil_space_create(name, space, flags, FIL_TABLESPACE,
NULL /* no encryption */,
true /* create */);
@ -2374,9 +2373,7 @@ innobase_start_or_create_for_mysql(void)
sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
fil_space_create(logfilename,
SRV_LOG_SPACE_FIRST_ID,
fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
FIL_LOG,
SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG,
NULL /* no encryption yet */,
true /* create */);
@ -2771,6 +2768,13 @@ files_checked:
}
if (!srv_read_only_mode) {
const ulint flags = FSP_FLAGS_PAGE_SSIZE();
for (ulint id = 0; id <= srv_undo_tablespaces; id++) {
if (fil_space_get(id)) {
fsp_flags_try_adjust(id, flags);
}
}
/* Create the thread which watches the timeouts
for lock waits */
thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create(

Loading…
Cancel
Save