MDEV-35494 fil_space_t::fil_space_t() may be unsafe with GCC -flifetime-dse

fil_space_t::create(): Instead of invoking the default fil_space_t
constructor on a zero-filled buffer, allocate an uninitialized buffer
and invoke an explicitly defined constructor on it. Also, specify
initializer expressions for all constant data members, so that all of them
will be initialized in the constructor.

fil_space_t::being_imported: Replaces part of fil_space_t::purpose.

fil_space_t::is_being_imported(), fil_space_t::is_temporary():
Replaces fil_space_t::purpose.

fil_space_t:🆔 Changed the type from ulint to uint32_t to reduce
incompatibility with later branches that include
commit ca501ffb04 (MDEV-26195).

fil_space_t::try_to_close(): Do not attempt to close files that are
in an I/O bound phase of ALTER TABLE…IMPORT TABLESPACE.

log_file_op, first_page_init: recv_spaces_t:
Use uint32_t for the tablespace id.

Reviewed by: Debarun Banerjee
This commit is contained in:
Marko Mäkelä 2024-12-11 14:44:42 +02:00
parent 7372ecc396
commit bfe7c8ff0a
21 changed files with 310 additions and 376 deletions

View file

@ -730,13 +730,15 @@ datafiles_iter_next(datafiles_iter_t *it)
fil_system.space_list.begin() :
std::next(it->space);
while (it->space != fil_system.space_list.end() &&
(it->space->purpose != FIL_TYPE_TABLESPACE ||
UT_LIST_GET_LEN(it->space->chain) == 0))
while (it->space != fil_system.space_list.end()
&& UT_LIST_GET_LEN(it->space->chain) == 0)
++it->space;
if (it->space == fil_system.space_list.end())
goto end;
ut_ad(!it->space->is_temporary());
ut_ad(!it->space->is_being_imported());
it->node = UT_LIST_GET_FIRST(it->space->chain);
end:
@ -907,7 +909,7 @@ err:
@param[in] len length of name, in bytes
@param[in] new_name new file name (NULL if not rename)
@param[in] new_len length of new_name, in bytes (0 if NULL) */
static void backup_file_op(ulint space_id, int type,
static void backup_file_op(uint32_t space_id, int type,
const byte* name, ulint len,
const byte* new_name, ulint new_len)
{
@ -923,7 +925,8 @@ static void backup_file_op(ulint space_id, int type,
std::string space_name = filename_to_spacename(name, len);
ddl_tracker.id_to_name[space_id] = space_name;
ddl_tracker.delete_defer(space_id, space_name);
msg("DDL tracking : create %zu \"%.*s\"", space_id, int(len), name);
msg("DDL tracking : create %" PRIu32 " \"%.*s\"",
space_id, int(len), name);
}
break;
case FILE_MODIFY:
@ -939,7 +942,7 @@ static void backup_file_op(ulint space_id, int type,
ddl_tracker.id_to_name[space_id] = new_space_name;
ddl_tracker.rename_defer(space_id, old_space_name,
new_space_name);
msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"",
msg("DDL tracking : rename %" PRIu32 " \"%.*s\",\"%.*s\"",
space_id, int(len), name, int(new_len), new_name);
}
break;
@ -947,7 +950,8 @@ static void backup_file_op(ulint space_id, int type,
ddl_tracker.drops.insert(space_id);
ddl_tracker.delete_defer(
space_id, filename_to_spacename(name, len));
msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name);
msg("DDL tracking : delete %" PRIu32 " \"%.*s\"",
space_id, int(len), name);
break;
default:
ut_ad(0);
@ -966,21 +970,22 @@ static void backup_file_op(ulint space_id, int type,
We will abort backup in this case.
*/
static void backup_file_op_fail(ulint space_id, int type,
static void backup_file_op_fail(uint32_t space_id, int type,
const byte* name, ulint len,
const byte* new_name, ulint new_len)
{
bool fail = false;
switch(type) {
case FILE_CREATE:
msg("DDL tracking : create %zu \"%.*s\"", space_id, int(len), name);
msg("DDL tracking : create %" PRIu32 " \"%.*s\"",
space_id, int(len), name);
fail = !check_if_skip_table(
filename_to_spacename(name, len).c_str());
break;
case FILE_MODIFY:
break;
case FILE_RENAME:
msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"",
msg("DDL tracking : rename %" PRIu32 " \"%.*s\",\"%.*s\"",
space_id, int(len), name, int(new_len), new_name);
fail = !check_if_skip_table(
filename_to_spacename(name, len).c_str())
@ -990,7 +995,8 @@ static void backup_file_op_fail(ulint space_id, int type,
case FILE_DELETE:
fail = !check_if_skip_table(
filename_to_spacename(name, len).c_str());
msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name);
msg("DDL tracking : delete %" PRIu32 " \"%.*s\"",
space_id, int(len), name);
break;
default:
ut_ad(0);
@ -1011,7 +1017,7 @@ static void backup_undo_trunc(uint32_t space_id)
/* Function to store the space id of page0 INIT_PAGE
@param space_id space id which has page0 init page */
static void backup_first_page_op(ulint space_id)
static void backup_first_page_op(uint32_t space_id)
{
first_page_init_ids.insert(space_id);
}
@ -3532,8 +3538,8 @@ static void xb_load_single_table_tablespace(const char *dirname,
if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) {
mysql_mutex_lock(&fil_system.mutex);
space = fil_space_t::create(
file->space_id(), file->flags(),
FIL_TYPE_TABLESPACE, nullptr/* TODO: crypt_data */,
uint32_t(file->space_id()), file->flags(), false,
nullptr/* TODO: crypt_data */,
FIL_ENCRYPTION_DEFAULT,
file->handle() != OS_FILE_CLOSED);
ut_ad(space);
@ -4998,8 +5004,8 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta)
iter != ddl_tracker.tables_in_backup.end();
iter++) {
const std::string name = iter->second;
ulint id = iter->first;
uint32_t id = iter->first;
const std::string &name = iter->second;
if (ddl_tracker.drops.find(id) != ddl_tracker.drops.end()) {
dropped_tables.insert(name);
@ -5025,8 +5031,8 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta)
iter != ddl_tracker.id_to_name.end();
iter++) {
ulint id = iter->first;
std::string name = iter->second;
uint32_t id = iter->first;
const std::string &name = iter->second;
if (ddl_tracker.tables_in_backup.find(id) != ddl_tracker.tables_in_backup.end()) {
/* already processed above */
@ -5322,8 +5328,8 @@ exit:
char tmpname[FN_REFLEN];
snprintf(tmpname, FN_REFLEN, "%s/xtrabackup_tmp_#" ULINTPF,
dbname, fil_space->id);
snprintf(tmpname, FN_REFLEN, "%s/xtrabackup_tmp_#%"
PRIu32, dbname, fil_space->id);
msg("mariabackup: Renaming %s to %s.ibd",
fil_space->chain.start->name, tmpname);
@ -5378,8 +5384,8 @@ exit:
ut_ad(fil_space_t::physical_size(flags) == info.page_size);
mysql_mutex_lock(&fil_system.mutex);
fil_space_t* space = fil_space_t::create(info.space_id, flags,
FIL_TYPE_TABLESPACE, 0,
fil_space_t* space = fil_space_t::create(uint32_t(info.space_id),
flags, false, 0,
FIL_ENCRYPTION_DEFAULT, true);
mysql_mutex_unlock(&fil_system.mutex);
if (space) {

View file

@ -3643,8 +3643,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t *bpage,
const bool seems_encrypted = !node.space->full_crc32() && key_version
&& node.space->crypt_data
&& node.space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED;
ut_ad(node.space->purpose != FIL_TYPE_TEMPORARY ||
node.space->full_crc32());
ut_ad(!node.space->is_temporary() || node.space->full_crc32());
/* If traditional checksums match, we assume that page is
not anymore encrypted. */
@ -3652,7 +3651,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t *bpage,
&& !buf_is_zeroes(span<const byte>(dst_frame,
node.space->physical_size()))
&& (key_version || node.space->is_compressed()
|| node.space->purpose == FIL_TYPE_TEMPORARY)) {
|| node.space->is_temporary())) {
if (buf_page_full_crc32_is_corrupted(
bpage->id().space(), dst_frame,
node.space->is_compressed())) {

View file

@ -750,7 +750,8 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size)
ut_ad(request.bpage);
ut_ad(request.bpage->in_file());
ut_ad(request.node);
ut_ad(request.node->space->purpose == FIL_TYPE_TABLESPACE);
ut_ad(!request.node->space->is_temporary());
ut_ad(!request.node->space->is_being_imported());
ut_ad(request.node->space->id == request.bpage->id().space());
ut_ad(request.node->space->referenced());
ut_ad(!srv_read_only_mode);

View file

@ -639,7 +639,7 @@ static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s,
fil_space_crypt_t *crypt_data= space->crypt_data;
bool encrypted, page_compressed;
if (space->purpose == FIL_TYPE_TEMPORARY)
if (space->is_temporary())
{
ut_ad(!crypt_data);
encrypted= innodb_encrypt_temporary_tables;
@ -685,13 +685,13 @@ static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s,
if (!page_compressed)
{
not_compressed:
d= space->purpose == FIL_TYPE_TEMPORARY
d= space->is_temporary()
? buf_tmp_page_encrypt(page_no, s, d)
: fil_space_encrypt(space, page_no, s, d);
}
else
{
ut_ad(space->purpose != FIL_TYPE_TEMPORARY);
ut_ad(!space->is_temporary());
/* First we compress the page content */
buf_tmp_reserve_compression_buf(*slot);
byte *tmp= (*slot)->comp_buf;
@ -768,8 +768,7 @@ bool buf_page_t::flush(fil_space_t *space)
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
ut_ad(in_file());
ut_ad(in_LRU_list);
ut_ad((space->purpose == FIL_TYPE_TEMPORARY) ==
(space == fil_system.temp_space));
ut_ad((space->is_temporary()) == (space == fil_system.temp_space));
ut_ad(space->referenced());
const auto s= state();
@ -779,12 +778,12 @@ bool buf_page_t::flush(fil_space_t *space)
(FIL_PAGE_LSN + (zip.data ? zip.data : frame)));
ut_ad(lsn
? lsn >= oldest_modification() || oldest_modification() == 2
: space->purpose != FIL_TYPE_TABLESPACE);
: (space->is_temporary() || space->is_being_imported()));
if (s < UNFIXED)
{
ut_a(s >= FREED);
if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE))
if (!space->is_temporary() && !space->is_being_imported())
{
freed:
if (lsn > log_sys.get_flushed_lsn())
@ -800,7 +799,8 @@ bool buf_page_t::flush(fil_space_t *space)
if (UNIV_UNLIKELY(lsn < space->get_create_lsn()))
{
ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
ut_ad(!space->is_temporary());
ut_ad(!space->is_being_imported());
goto freed;
}
@ -884,7 +884,7 @@ bool buf_page_t::flush(fil_space_t *space)
if ((s & LRU_MASK) == REINIT || !space->use_doublewrite())
{
if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE) &&
if (!space->is_temporary() && !space->is_being_imported() &&
lsn > log_sys.get_flushed_lsn())
log_write_up_to(lsn, true);
space->io(IORequest{type, this, slot}, physical_offset(), size,
@ -1735,7 +1735,7 @@ done:
if (acquired)
space->release();
if (space->purpose == FIL_TYPE_IMPORT)
if (space->is_being_imported())
os_aio_wait_until_no_pending_writes(true);
else
buf_dblwr.flush_buffered_writes();

View file

@ -972,8 +972,10 @@ void dict_check_tablespaces_and_store_max_id(const std::set<uint32_t> *spaces)
const bool not_dropped{!rec_get_deleted_flag(rec, 0)};
/* Check that the .ibd file exists. */
if (fil_ibd_open(not_dropped, FIL_TYPE_TABLESPACE,
space_id, dict_tf_to_fsp_flags(flags),
if (fil_ibd_open(space_id, dict_tf_to_fsp_flags(flags),
not_dropped
? fil_space_t::VALIDATE_NOTHING
: fil_space_t::MAYBE_MISSING,
name, filepath)) {
} else if (!not_dropped) {
} else if (srv_operation == SRV_OPERATION_NORMAL
@ -2291,8 +2293,8 @@ dict_load_tablespace(
}
table->space = fil_ibd_open(
2, FIL_TYPE_TABLESPACE, table->space_id,
dict_tf_to_fsp_flags(table->flags),
table->space_id, dict_tf_to_fsp_flags(table->flags),
fil_space_t::VALIDATE_SPACE_ID,
{table->name.m_name, strlen(table->name.m_name)}, filepath);
if (!table->space) {

View file

@ -136,9 +136,6 @@ dict_table_t *dict_table_t::create(const span<const char> &name,
ulint n_cols, ulint n_v_cols, ulint flags,
ulint flags2)
{
ut_ad(!space || space->purpose == FIL_TYPE_TABLESPACE ||
space->purpose == FIL_TYPE_TEMPORARY ||
space->purpose == FIL_TYPE_IMPORT);
ut_a(dict_tf2_is_valid(flags, flags2));
ut_a(!(flags2 & DICT_TF2_UNUSED_BIT_MASK));

View file

@ -1067,7 +1067,8 @@ default_encrypt_list only when
default encrypt */
static bool fil_crypt_must_remove(const fil_space_t &space)
{
ut_ad(space.purpose == FIL_TYPE_TABLESPACE);
ut_ad(!space.is_temporary());
ut_ad(!space.is_being_imported());
fil_space_crypt_t *crypt_data = space.crypt_data;
mysql_mutex_assert_owner(&fil_system.mutex);
const ulong encrypt_tables= srv_encrypt_tables;
@ -1103,7 +1104,8 @@ fil_crypt_space_needs_rotation(
fil_space_t* space = &*state->space;
ut_ad(space->referenced());
ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
ut_ad(!space->is_temporary());
ut_ad(!space->is_being_imported());
fil_space_crypt_t *crypt_data = space->crypt_data;
@ -1455,7 +1457,7 @@ space_list_t::iterator fil_space_t::next(space_list_t::iterator space,
for (; space != fil_system.space_list.end(); ++space)
{
if (space->purpose != FIL_TYPE_TABLESPACE)
if (space->is_temporary() || space->is_being_imported())
continue;
const uint32_t n= space->acquire_low();
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
@ -2137,9 +2139,9 @@ static void fil_crypt_default_encrypt_tables_fill()
mysql_mutex_assert_owner(&fil_system.mutex);
for (fil_space_t& space : fil_system.space_list) {
if (space.purpose != FIL_TYPE_TABLESPACE
|| space.is_in_default_encrypt
if (space.is_in_default_encrypt
|| UT_LIST_GET_LEN(space.chain) == 0
|| space.is_temporary() || space.is_being_imported()
|| !space.acquire_if_not_stopped()) {
continue;
}

View file

@ -81,17 +81,10 @@ bool fil_space_t::try_to_close(fil_space_t *ignore_space, bool print_info)
mysql_mutex_assert_owner(&fil_system.mutex);
for (fil_space_t &space : fil_system.space_list)
{
if (&space == ignore_space)
if (&space == ignore_space || space.is_being_imported() ||
!fil_is_user_tablespace_id(space.id))
continue;
switch (space.purpose) {
case FIL_TYPE_TEMPORARY:
continue;
case FIL_TYPE_IMPORT:
break;
case FIL_TYPE_TABLESPACE:
if (!fil_is_user_tablespace_id(space.id))
continue;
}
ut_ad(!space.is_temporary());
/* We are using an approximation of LRU replacement policy. In
fil_node_open_file_low(), newly opened files are moved to the end
@ -432,7 +425,7 @@ static bool fil_node_open_file(fil_node_t *node, const byte *page, bool no_lsn)
srv_operation == SRV_OPERATION_BACKUP ||
srv_operation == SRV_OPERATION_RESTORE ||
srv_operation == SRV_OPERATION_RESTORE_DELTA);
ut_ad(node->space->purpose != FIL_TYPE_TEMPORARY);
ut_ad(!node->space->is_temporary());
ut_ad(node->space->referenced());
const auto old_time= fil_system.n_open_exceeded_time;
@ -493,7 +486,7 @@ void fil_node_t::prepare_to_close_or_detach()
srv_operation == SRV_OPERATION_RESTORE_DELTA);
ut_a(is_open());
ut_a(!being_extended);
ut_a(space->is_ready_to_close() || space->purpose == FIL_TYPE_TEMPORARY ||
ut_a(space->is_ready_to_close() || space->is_temporary() ||
srv_fast_shutdown == 2 || !srv_was_started);
ut_a(fil_system.n_open > 0);
@ -650,14 +643,13 @@ fil_space_extend_must_retry(
mysql_mutex_lock(&fil_system.mutex);
break;
default:
ut_ad(space->purpose == FIL_TYPE_TABLESPACE
|| space->purpose == FIL_TYPE_IMPORT);
if (space->purpose == FIL_TYPE_TABLESPACE) {
ut_ad(!space->is_temporary());
if (!space->is_being_imported()) {
goto do_flush;
}
break;
case SRV_TMP_SPACE_ID:
ut_ad(space->purpose == FIL_TYPE_TEMPORARY);
ut_ad(space->is_temporary());
srv_tmp_space.set_last_file_size(pages_in_MiB);
break;
}
@ -671,8 +663,7 @@ ATTRIBUTE_COLD bool fil_space_t::prepare_acquired()
ut_ad(referenced());
mysql_mutex_assert_owner(&fil_system.mutex);
fil_node_t *node= UT_LIST_GET_LAST(chain);
ut_ad(!id || purpose == FIL_TYPE_TEMPORARY ||
node == UT_LIST_GET_FIRST(chain));
ut_ad(!id || is_temporary() || node == UT_LIST_GET_FIRST(chain));
const bool is_open= node &&
(node->is_open() || fil_node_open_file(node, nullptr, false));
@ -734,7 +725,7 @@ ATTRIBUTE_COLD bool fil_space_t::acquire_and_prepare()
@return whether the tablespace is at least as big as requested */
bool fil_space_extend(fil_space_t *space, uint32_t size)
{
ut_ad(!srv_read_only_mode || space->purpose == FIL_TYPE_TEMPORARY);
ut_ad(!srv_read_only_mode || space->is_temporary());
bool success= false;
const bool acquired= space->acquire();
mysql_mutex_lock(&fil_system.mutex);
@ -942,111 +933,87 @@ fil_space_free(
return(space != NULL);
}
/** Create a tablespace in fil_system.
@param name tablespace name
@param id tablespace identifier
@param flags tablespace flags
@param purpose tablespace purpose
@param crypt_data encryption information
@param mode encryption mode
@param opened true if space files are opened
@return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */
fil_space_t *fil_space_t::create(ulint id, ulint flags,
fil_type_t purpose,
fil_space_crypt_t *crypt_data,
fil_encryption_t mode,
bool opened)
fil_space_t::fil_space_t(uint32_t id, ulint flags, bool being_imported,
fil_space_crypt_t *crypt_data) noexcept :
id(id), crypt_data(crypt_data), being_imported(being_imported), flags(flags)
{
fil_space_t* space;
UT_LIST_INIT(chain, &fil_node_t::chain);
#ifndef SUX_LOCK_GENERIC
memset((void*) &latch, 0, sizeof latch);
#endif
latch.SRW_LOCK_INIT(fil_space_latch_key);
}
mysql_mutex_assert_owner(&fil_system.mutex);
ut_ad(fil_system.is_initialised());
ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
ut_ad(srv_page_size == UNIV_PAGE_SIZE_ORIG || flags != 0);
fil_space_t *fil_space_t::create(uint32_t id, ulint flags,
bool being_imported,
fil_space_crypt_t *crypt_data,
fil_encryption_t mode,
bool opened) noexcept
{
mysql_mutex_assert_owner(&fil_system.mutex);
ut_ad(fil_system.is_initialised());
ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
ut_ad(srv_page_size == UNIV_PAGE_SIZE_ORIG || flags != 0);
DBUG_EXECUTE_IF("fil_space_create_failure", return(NULL););
DBUG_EXECUTE_IF("fil_space_create_failure", return nullptr;);
fil_space_t** after = reinterpret_cast<fil_space_t**>(
&fil_system.spaces.cell_get(id)->node);
for (; *after; after = &(*after)->hash) {
ut_a((*after)->id != id);
}
fil_space_t** after= fil_system.spaces.cell_get(id)->search
(&fil_space_t::hash, [id](const fil_space_t *space)
{ return !space || space->id == id; });
ut_a(!*after);
fil_space_t *space= new (ut_malloc_nokey(sizeof(*space)))
fil_space_t(id, flags, being_imported, crypt_data);
*after= space;
/* FIXME: if calloc() is defined as an inline function that calls
memset() or bzero(), then GCC 6 -flifetime-dse can optimize it away */
*after = space = new (ut_zalloc_nokey(sizeof(*space))) fil_space_t;
if (crypt_data)
DBUG_PRINT("crypt", ("Tablespace %" PRIu32 " encryption %d key id %" PRIu32
":%s %s",
id, crypt_data->encryption, crypt_data->key_id,
fil_crypt_get_mode(crypt_data),
fil_crypt_get_type(crypt_data)));
space->id = id;
if (opened)
fil_system.add_opened_last_to_space_list(space);
else
fil_system.space_list.push_back(*space);
UT_LIST_INIT(space->chain, &fil_node_t::chain);
switch (id) {
case 0:
ut_ad(!fil_system.sys_space);
fil_system.sys_space= space;
break;
case SRV_TMP_SPACE_ID:
ut_ad(!fil_system.temp_space);
fil_system.temp_space= space;
return space;
default:
if (UNIV_LIKELY(id <= fil_system.max_assigned_id))
break;
if (UNIV_UNLIKELY(srv_operation == SRV_OPERATION_BACKUP))
break;
if (!fil_system.space_id_reuse_warned)
sql_print_warning("InnoDB: Allocated tablespace ID %" PRIu32
", old maximum was %" PRIu32,
id, fil_system.max_assigned_id);
fil_system.max_assigned_id = id;
}
space->purpose = purpose;
space->flags = flags;
if ((mode == FIL_ENCRYPTION_ON ||
(mode == FIL_ENCRYPTION_OFF || srv_encrypt_tables)) &&
!space->is_being_imported() && fil_crypt_must_default_encrypt())
{
fil_system.default_encrypt_tables.push_back(*space);
space->is_in_default_encrypt= true;
space->crypt_data = crypt_data;
space->n_pending.store(CLOSING, std::memory_order_relaxed);
if (srv_n_fil_crypt_threads_started)
{
mysql_mutex_unlock(&fil_system.mutex);
fil_crypt_threads_signal();
mysql_mutex_lock(&fil_system.mutex);
}
}
DBUG_LOG("tablespace", "Created metadata for " << id);
if (crypt_data) {
DBUG_LOG("crypt",
"Tablespace " << id
<< " encryption " << crypt_data->encryption
<< " key id " << crypt_data->key_id
<< ":" << fil_crypt_get_mode(crypt_data)
<< " " << fil_crypt_get_type(crypt_data));
}
space->latch.SRW_LOCK_INIT(fil_space_latch_key);
if (opened)
fil_system.add_opened_last_to_space_list(space);
else
fil_system.space_list.push_back(*space);
switch (id) {
case 0:
ut_ad(!fil_system.sys_space);
fil_system.sys_space = space;
break;
case SRV_TMP_SPACE_ID:
ut_ad(!fil_system.temp_space);
fil_system.temp_space = space;
break;
default:
ut_ad(purpose != FIL_TYPE_TEMPORARY);
if (UNIV_LIKELY(id <= fil_system.max_assigned_id)) {
break;
}
if (UNIV_UNLIKELY(srv_operation == SRV_OPERATION_BACKUP)) {
break;
}
if (!fil_system.space_id_reuse_warned) {
ib::warn() << "Allocated tablespace ID " << id
<< ", old maximum was "
<< fil_system.max_assigned_id;
}
fil_system.max_assigned_id = id;
}
const bool rotate = purpose == FIL_TYPE_TABLESPACE
&& (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF
|| srv_encrypt_tables)
&& fil_crypt_must_default_encrypt();
if (rotate) {
fil_system.default_encrypt_tables.push_back(*space);
space->is_in_default_encrypt = true;
if (srv_n_fil_crypt_threads_started) {
mysql_mutex_unlock(&fil_system.mutex);
fil_crypt_threads_signal();
mysql_mutex_lock(&fil_system.mutex);
}
}
return(space);
return space;
}
/*******************************************************************//**
@ -1580,6 +1547,7 @@ fil_name_write(
fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle)
{
ut_a(!is_system_tablespace(id));
ut_ad(id != SRV_TMP_SPACE_ID);
mysql_mutex_lock(&fil_system.mutex);
fil_space_t *space= fil_space_get_by_id(id);
@ -1622,7 +1590,7 @@ fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle)
if (space->crypt_data)
fil_space_crypt_close_tablespace(space);
if (space->purpose == FIL_TYPE_TABLESPACE)
if (!space->is_being_imported())
{
/* Before deleting the file, persistently write a log record. */
mtr_t mtr;
@ -1635,8 +1603,6 @@ fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle)
os_file_delete(innodb_data_file_key, space->chain.start->name);
}
else
ut_ad(space->purpose == FIL_TYPE_IMPORT);
if (char *cfg_name= fil_make_filepath(space->chain.start->name,
fil_space_t::name_type{}, CFG, false))
@ -1935,7 +1901,7 @@ fil_ibd_create(
uint32_t size,
fil_encryption_t mode,
uint32_t key_id,
dberr_t* err)
dberr_t* err) noexcept
{
pfs_os_file_t file;
bool success;
@ -2055,8 +2021,8 @@ err_exit:
log_make_checkpoint(););
mysql_mutex_lock(&fil_system.mutex);
if (fil_space_t* space = fil_space_t::create(space_id, flags,
FIL_TYPE_TABLESPACE,
if (fil_space_t* space = fil_space_t::create(uint32_t(space_id),
flags, false,
crypt_data, mode, true)) {
fil_node_t* node = space->add(path, file, size, false, true);
node->find_metadata(IF_WIN(,true));
@ -2078,51 +2044,17 @@ err_exit:
goto err_exit;
}
/** Try to open a single-table tablespace and optionally check that the
space id in it is correct. If this does not succeed, print an error message
to the .err log. This function is used to open a tablespace when we start
mysqld after the dictionary has been booted, and also in IMPORT TABLESPACE.
NOTE that we assume this operation is used either at the database startup
or under the protection of dict_sys.latch, so that two users cannot
race here. This operation does not leave the file associated with the
tablespace open, but closes it after we have looked at the space id in it.
If the validate boolean is set, we read the first page of the file and
check that the space id in the file is what we expect. We assume that
this function runs much faster if no check is made, since accessing the
file inode probably is much faster (the OS caches them) than accessing
the first page of the file. This boolean may be initially false, but if
a remote tablespace is found it will be changed to true.
If the fix_dict boolean is set, then it is safe to use an internal SQL
statement to update the dictionary tables if they are incorrect.
@param[in] validate 0=maybe missing, 1=do not validate, 2=validate
@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_TEMPORARY
@param[in] id tablespace ID
@param[in] flags expected FSP_SPACE_FLAGS
@param[in] name table name
If file-per-table, it is the table name in the databasename/tablename format
@param[in] path_in expected filepath, usually read from dictionary
@param[out] err DB_SUCCESS or error code
@return tablespace
@retval NULL if the tablespace could not be opened */
fil_space_t*
fil_ibd_open(
unsigned validate,
fil_type_t purpose,
ulint id,
ulint flags,
fil_space_t::name_type name,
const char* path_in,
dberr_t* err)
fil_space_t *fil_ibd_open(ulint id, ulint flags,
fil_space_t::validate validate,
fil_space_t::name_type name,
const char *path_in, dberr_t *err) noexcept
{
mysql_mutex_lock(&fil_system.mutex);
fil_space_t* space = fil_space_get_by_id(id);
mysql_mutex_unlock(&fil_system.mutex);
if (space) {
if (validate > 1 && !srv_read_only_mode) {
if (validate == fil_space_t::VALIDATE_SPACE_ID
&& !srv_read_only_mode) {
fsp_flags_try_adjust(space,
flags & ~FSP_FLAGS_MEM_MASK);
}
@ -2148,8 +2080,8 @@ func_exit:
ulint tablespaces_found = 0;
ulint valid_tablespaces_found = 0;
df_default.init(flags);
df_remote.init(flags);
df_default.init(uint32_t(flags));
df_remote.init(uint32_t(flags));
/* Discover the correct file by looking in three possible locations
while avoiding unecessary effort. */
@ -2178,7 +2110,7 @@ func_exit:
/* Dict path is not the default path. Always validate
remote files. If default is opened, it was moved. */
must_validate = true;
} else if (validate > 1) {
} else if (validate >= fil_space_t::VALIDATE_SPACE_ID) {
must_validate = true;
}
@ -2195,7 +2127,8 @@ func_exit:
the first server startup. The tables ought to be dropped by
drop_garbage_tables_after_restore() a little later. */
const bool strict = validate && !tablespaces_found
const bool strict = (validate != fil_space_t::MAYBE_MISSING)
&& !tablespaces_found
&& operation_not_for_export
&& !(srv_operation == SRV_OPERATION_NORMAL
&& srv_start_after_restore
@ -2326,7 +2259,9 @@ skip_validate:
: NULL;
mysql_mutex_lock(&fil_system.mutex);
space = fil_space_t::create(id, flags, purpose, crypt_data);
space = fil_space_t::create(uint32_t(id), flags,
validate == fil_space_t::VALIDATE_IMPORT,
crypt_data);
if (!space) {
mysql_mutex_unlock(&fil_system.mutex);
goto error;
@ -2344,7 +2279,7 @@ skip_validate:
df_remote.close();
df_default.close();
if (space->acquire()) {
if (purpose != FIL_TYPE_IMPORT) {
if (validate < fil_space_t::VALIDATE_IMPORT) {
fsp_flags_try_adjust(space, flags
& ~FSP_FLAGS_MEM_MASK);
}
@ -2632,8 +2567,8 @@ tablespace_check:
mysql_mutex_lock(&fil_system.mutex);
space = fil_space_t::create(
space_id, flags, FIL_TYPE_TABLESPACE, crypt_data);
space = fil_space_t::create(uint32_t(space_id), flags, false,
crypt_data);
if (space == NULL) {
mysql_mutex_unlock(&fil_system.mutex);
@ -2661,16 +2596,14 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
{
ut_ad(!srv_read_only_mode);
ut_ad(fil_space_t::is_valid_flags(flags, space->id));
ut_ad(!space->is_being_imported());
ut_ad(!space->is_temporary());
if (space->full_crc32() || fil_space_t::full_crc32(flags)) {
return;
}
if (!space->size && (space->purpose != FIL_TYPE_TABLESPACE
|| !space->get_size())) {
if (!space->size || !space->get_size()) {
return;
}
/* This code is executed during server startup while no
connections are allowed. We do not need to protect against
DROP TABLE by fil_space_acquire(). */
mtr_t mtr;
mtr.start();
if (buf_block_t* b = buf_page_get(
@ -2760,7 +2693,7 @@ inline void fil_node_t::complete_write()
{
mysql_mutex_assert_not_owner(&fil_system.mutex);
if (space->purpose != FIL_TYPE_TEMPORARY &&
if (!space->is_temporary() &&
srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC &&
space->set_needs_flush())
{
@ -3074,8 +3007,8 @@ fil_space_validate_for_mtr_commit(
{
mysql_mutex_assert_not_owner(&fil_system.mutex);
ut_ad(space != NULL);
ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
ut_ad(!is_predefined_tablespace(space->id));
ut_ad(!space->is_being_imported());
/* We are serving mtr_commit(). While there is an active
mini-transaction, we should have !space->is_stopping(). This is
@ -3290,7 +3223,7 @@ fil_space_t::name_type fil_space_t::name() const
if (!UT_LIST_GET_FIRST(chain) || srv_is_undo_tablespace(id))
return name_type{};
ut_ad(purpose != FIL_TYPE_TEMPORARY);
ut_ad(!is_temporary());
ut_ad(UT_LIST_GET_LEN(chain) == 1);
const char *path= UT_LIST_GET_FIRST(chain)->name;

View file

@ -352,7 +352,7 @@ xdes_get_descriptor_with_space_hdr(
ut_ad(limit == space->free_limit
|| (space->free_limit == 0
&& (init_space
|| space->purpose == FIL_TYPE_TEMPORARY
|| space->is_temporary()
|| (srv_startup_is_before_trx_rollback_phase
&& (space->id == TRX_SYS_SPACE
|| srv_is_undo_tablespace(space->id))))));
@ -490,14 +490,15 @@ void fil_space_t::modify_check(const mtr_t& mtr) const
case MTR_LOG_NONE:
/* These modes are only allowed within a non-bitmap page
when there is a higher-level redo log record written. */
ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_TEMPORARY);
ut_ad(!is_being_imported());
break;
case MTR_LOG_NO_REDO:
ut_ad(purpose == FIL_TYPE_TEMPORARY || purpose == FIL_TYPE_IMPORT);
ut_ad(is_temporary() || is_being_imported());
break;
default:
/* We may only write redo log for a persistent tablespace. */
ut_ad(purpose == FIL_TYPE_TABLESPACE);
ut_ad(!is_temporary());
ut_ad(!is_being_imported());
ut_ad(mtr.is_named_space(id));
}
}
@ -857,7 +858,7 @@ fsp_fill_free_list(
FIL_PAGE_TYPE_XDES);
}
if (space->purpose != FIL_TYPE_TEMPORARY)
if (!space->is_temporary())
{
buf_block_t *f= buf_LRU_get_free_block(false);
buf_block_t *block=

View file

@ -132,10 +132,8 @@ Tablespace::open_or_create(bool is_temp)
mysql_mutex_lock(&fil_system.mutex);
space = fil_space_t::create(
m_space_id, fsp_flags,
is_temp
? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE,
NULL);
uint32_t(m_space_id), fsp_flags,
false, nullptr);
if (!space) {
mysql_mutex_unlock(&fil_system.mutex);
return DB_ERROR;

View file

@ -936,8 +936,7 @@ SysTablespace::open_or_create(
} else if (is_temp) {
ut_ad(space_id() == SRV_TMP_SPACE_ID);
space = fil_space_t::create(
SRV_TMP_SPACE_ID, flags(),
FIL_TYPE_TEMPORARY, NULL);
SRV_TMP_SPACE_ID, flags(), false, nullptr);
ut_ad(space == fil_system.temp_space);
if (!space) {
err = DB_ERROR;
@ -948,8 +947,7 @@ SysTablespace::open_or_create(
} else {
ut_ad(space_id() == TRX_SYS_SPACE);
space = fil_space_t::create(
TRX_SYS_SPACE, it->flags(),
FIL_TYPE_TABLESPACE, NULL);
TRX_SYS_SPACE, it->flags(), false, nullptr);
ut_ad(space == fil_system.sys_space);
if (!space) {
err = DB_ERROR;

View file

@ -6562,7 +6562,8 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*)
for (fil_space_t &space : fil_system.space_list)
{
if (space.purpose == FIL_TYPE_TABLESPACE && !space.is_stopping() &&
if (!space.is_temporary() && !space.is_being_imported() &&
!space.is_stopping() &&
space.chain.start)
{
space.reacquire();
@ -6734,7 +6735,7 @@ i_s_dict_fill_tablespaces_encryption(
} else if (srv_is_undo_tablespace(space->id)) {
char undo_name[sizeof "innodb_undo000"];
snprintf(undo_name, sizeof(undo_name),
"innodb_undo%03zu",space->id);
"innodb_undo%03" PRIu32, space->id);
OK(fields[TABLESPACES_ENCRYPTION_NAME]->store(
undo_name, strlen(undo_name),
system_charset_info));
@ -6802,7 +6803,7 @@ i_s_tablespaces_encryption_fill_table(
fil_system.freeze_space_list++;
for (fil_space_t& space : fil_system.space_list) {
if (space.purpose == FIL_TYPE_TABLESPACE
if (!space.is_temporary() && !space.is_being_imported()
&& !space.is_stopping()) {
space.reacquire();
mysql_mutex_unlock(&fil_system.mutex);

View file

@ -738,13 +738,15 @@ ibuf_set_free_bits_func(
mtr.start();
const page_id_t id(block->page.id());
const fil_space_t *space= mtr.set_named_space_id(id.space());
/* all callers of ibuf_update_free_bits_if_full() or ibuf_reset_free_bits()
check this */
ut_ad(!space->is_temporary());
if (buf_block_t *bitmap_page=
ibuf_bitmap_get_map_page(id, block->zip_size(), &mtr))
{
if (space->purpose != FIL_TYPE_TABLESPACE)
if (space->is_being_imported()) /* IndexPurge may invoke this */
mtr.set_log_mode(MTR_LOG_NO_REDO);
#ifdef UNIV_IBUF_DEBUG
if (max_val != ULINT_UNDEFINED)
{
@ -925,8 +927,7 @@ ibuf_page_low(
return(false);
}
compile_time_assert(IBUF_SPACE_ID == 0);
ut_ad(fil_system.sys_space->purpose == FIL_TYPE_TABLESPACE);
static_assert(IBUF_SPACE_ID == 0, "compatiblity");
#ifdef UNIV_DEBUG
if (x_latch) {
@ -4498,7 +4499,7 @@ ibuf_print(
dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
{
ut_ad(trx->mysql_thd);
ut_ad(space->purpose == FIL_TYPE_IMPORT);
ut_ad(space->is_being_imported());
const unsigned zip_size = space->zip_size();
const unsigned physical_size = space->physical_size();

View file

@ -100,16 +100,6 @@ class page_id_t;
/** Structure containing encryption specification */
struct fil_space_crypt_t;
/** File types */
enum fil_type_t {
/** temporary tablespace (temporary undo log or tables) */
FIL_TYPE_TEMPORARY,
/** a tablespace that is being imported (no logging until finished) */
FIL_TYPE_IMPORT,
/** persistent tablespace (for system, undo log or tables) */
FIL_TYPE_TABLESPACE,
};
struct fil_node_t;
/** Structure to store first and last value of range */
@ -344,42 +334,43 @@ struct fil_space_t final
{
#ifndef UNIV_INNOCHECKSUM
friend fil_node_t;
/** Constructor; see @fil_space_t::create() */
inline explicit fil_space_t(uint32_t id, ulint flags, bool being_imported,
fil_space_crypt_t *crypt_data) noexcept;
~fil_space_t()
{
ut_ad(!latch_owner);
latch.destroy();
}
ulint id; /*!< space id */
/** tablespace identifier */
uint32_t id;
/** fil_system.spaces chain node */
fil_space_t *hash;
lsn_t max_lsn;
/*!< LSN of the most recent
fil_names_write_if_was_clean().
Reset to 0 by fil_names_clear().
Protected by log_sys.mutex.
If and only if this is nonzero, the
tablespace will be in named_spaces. */
fil_type_t purpose;/*!< purpose */
UT_LIST_BASE_NODE_T(fil_node_t) chain;
/*!< base node for the file chain */
uint32_t size; /*!< tablespace file size in pages;
0 if not known yet */
uint32_t size_in_header;
/* FSP_SIZE in the tablespace header;
0 if not known yet */
uint32_t free_len;
/*!< length of the FSP_FREE list */
uint32_t free_limit;
/*!< contents of FSP_FREE_LIMIT */
uint32_t recv_size;
/*!< recovered tablespace size in pages;
0 if no size change was read from the redo log,
or if the size change was implemented */
uint32_t n_reserved_extents;
/*!< number of reserved free extents for
ongoing operations like B-tree page split */
fil_space_t *hash= nullptr;
/** log_sys.get_lsn() of the most recent fil_names_write_if_was_clean().
Reset to 0 by fil_names_clear(). Protected by log_sys.mutex.
If and only if this is nonzero, the tablespace will be in named_spaces. */
lsn_t max_lsn= 0;
/** base node for the chain of data files; multiple entries are
only possible for is_temporary() or id==0 */
UT_LIST_BASE_NODE_T(fil_node_t) chain;
/** tablespace size in pages; 0 if not determined yet */
uint32_t size= 0;
/** FSP_SIZE in the tablespace header; 0 if not determined yet */
uint32_t size_in_header= 0;
/** length of the FSP_FREE list */
uint32_t free_len= 0;
/** contents of FSP_FREE_LIMIT */
uint32_t free_limit= 0;
/** recovered tablespace size in pages; 0 if no size change was read
from the redo log, or if the size change was applied */
uint32_t recv_size= 0;
/** number of reserved free extents for ongoing operations like
B-tree page split */
uint32_t n_reserved_extents= 0;
private:
#ifdef UNIV_DEBUG
fil_space_t *next_in_space_list();
@ -390,10 +381,10 @@ private:
#endif
/** the committed size of the tablespace in pages */
Atomic_relaxed<uint32_t> committed_size;
Atomic_relaxed<uint32_t> committed_size{0};
/** Number of pending operations on the file.
The tablespace cannot be freed while (n_pending & PENDING) != 0. */
std::atomic<uint32_t> n_pending;
std::atomic<uint32_t> n_pending{CLOSING};
/** Flag in n_pending that indicates that the tablespace is about to be
deleted, and no further operations should be performed */
static constexpr uint32_t STOPPING_READS= 1U << 31;
@ -415,20 +406,23 @@ private:
/** latch protecting all page allocation bitmap pages */
IF_DBUG(srw_lock_debug, srw_lock) latch;
/** the thread that holds the exclusive latch, or 0 */
pthread_t latch_owner;
pthread_t latch_owner= 0;
public:
/** MariaDB encryption data */
fil_space_crypt_t *crypt_data;
fil_space_crypt_t *crypt_data= nullptr;
/** Whether needs_flush(), or this is in fil_system.unflushed_spaces */
bool is_in_unflushed_spaces;
bool is_in_unflushed_spaces= false;
/** Whether this in fil_system.default_encrypt_tables (needs key rotation) */
bool is_in_default_encrypt;
bool is_in_default_encrypt= false;
private:
/** Whether the tablespace is being imported */
bool being_imported= false;
/** Whether any corrupton of this tablespace has been reported */
mutable std::atomic_flag is_corrupted;
mutable std::atomic_flag is_corrupted{false};
/** mutex to protect freed_ranges and last_freed_lsn */
std::mutex freed_range_mutex;
@ -437,11 +431,18 @@ private:
range_set freed_ranges;
/** LSN of freeing last page; protected by freed_range_mutex */
lsn_t last_freed_lsn;
lsn_t last_freed_lsn= 0;
/** LSN of undo tablespace creation or 0; protected by latch */
lsn_t create_lsn;
lsn_t create_lsn= 0;
public:
/** @return whether this is the temporary tablespace */
bool is_temporary() const noexcept
{ return UNIV_UNLIKELY(id == SRV_TMP_SPACE_ID); }
/** @return whether this tablespace is being imported */
bool is_being_imported() const noexcept
{ return UNIV_UNLIKELY(being_imported); }
/** @return whether doublewrite buffering is needed */
inline bool use_doublewrite() const;
@ -511,7 +512,7 @@ public:
MY_ATTRIBUTE((nonnull));
/** Note that the tablespace has been imported.
Initially, purpose=FIL_TYPE_IMPORT so that no redo log is
Initially, purpose=IMPORT so that no redo log is
written while the space ID is being updated in each page. */
inline void set_imported();
@ -946,18 +947,18 @@ public:
#ifndef UNIV_INNOCHECKSUM
MY_ATTRIBUTE((warn_unused_result))
/** Create a tablespace in fil_system.
@param id tablespace identifier
@param flags tablespace flags
@param purpose tablespace purpose
@param crypt_data encryption information
@param mode encryption mode
@param opened true if space files are opened
@param id tablespace identifier
@param flags tablespace flags
@param being_imported whether this is IMPORT TABLESPACE
@param crypt_data encryption information
@param mode encryption mode
@param opened whether the tablespace files are open
@return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */
static fil_space_t *create(ulint id, ulint flags,
fil_type_t purpose, fil_space_crypt_t *crypt_data,
static fil_space_t *create(uint32_t id, ulint flags, bool being_imported,
fil_space_crypt_t *crypt_data,
fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT,
bool opened= false);
bool opened= false) noexcept;
MY_ATTRIBUTE((warn_unused_result))
/** Acquire a tablespace reference.
@ -1079,6 +1080,18 @@ public:
/** @return the tablespace name (databasename/tablename) */
name_type name() const;
/** How to validate tablespace files that are being opened */
enum validate {
/** the file may be missing */
MAYBE_MISSING= 0,
/** do not validate */
VALIDATE_NOTHING,
/** validate the tablespace ID */
VALIDATE_SPACE_ID,
/** opening a file for ALTER TABLE...IMPORT TABLESPACE */
VALIDATE_IMPORT
};
private:
/** @return whether the file is usable for io() */
ATTRIBUTE_COLD bool prepare_acquired();
@ -1163,8 +1176,8 @@ inline bool fil_space_t::use_doublewrite() const
inline void fil_space_t::set_imported()
{
ut_ad(purpose == FIL_TYPE_IMPORT);
purpose= FIL_TYPE_TABLESPACE;
ut_ad(being_imported);
being_imported= false;
UT_LIST_GET_FIRST(chain)->find_metadata();
}
@ -1478,12 +1491,9 @@ public:
ulint n_open;
/** last time we noted n_open exceeding the limit; protected by mutex */
time_t n_open_exceeded_time;
ulint max_assigned_id;/*!< maximum space id in the existing
tables, or assigned during the time
mysqld has been up; at an InnoDB
startup we scan the data dictionary
and set here the maximum of the
space id's of the tables there */
/** maximum space id in the existing tables; on InnoDB startup this is
initialized based on the data dictionary contents */
ulint max_assigned_id;
/** nonzero if fil_node_open_file_low() should avoid moving the tablespace
to the end of space_list, for FIFO policy of try_to_close() */
ulint freeze_space_list;
@ -1588,7 +1598,7 @@ template<bool have_reference> inline void fil_space_t::flush()
{
mysql_mutex_assert_not_owner(&fil_system.mutex);
ut_ad(!have_reference || (pending() & PENDING));
ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT);
ut_ad(!is_temporary());
if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC)
{
ut_ad(!is_in_unflushed_spaces);
@ -1729,7 +1739,7 @@ fil_ibd_create(
uint32_t size,
fil_encryption_t mode,
uint32_t key_id,
dberr_t* err)
dberr_t* err) noexcept
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations.
@ -1738,43 +1748,28 @@ fil_ibd_create(
@param[in] flags desired tablespace flags */
void fsp_flags_try_adjust(fil_space_t* space, 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
function is used to open a tablespace when we start up mysqld, and also in
IMPORT TABLESPACE.
NOTE that we assume this operation is used either at the database startup
or under the protection of dict_sys.latch, so that two users cannot
race here. This operation does not leave the file associated with the
tablespace open, but closes it after we have looked at the space id in it.
If the validate boolean is set, we read the first page of the file and
check that the space id in the file is what we expect. We assume that
this function runs much faster if no check is made, since accessing the
file inode probably is much faster (the OS caches them) than accessing
the first page of the file. This boolean may be initially false, but if
a remote tablespace is found it will be changed to true.
NOTE that we assume this operation is used either at the database
startup or under the protection of MDL, to prevent concurrent access
to the same tablespace.
@param[in] validate 0=maybe missing, 1=do not validate, 2=validate
@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_TEMPORARY
@param[in] id tablespace ID
@param[in] flags expected FSP_SPACE_FLAGS
@param[in] name table name
If file-per-table, it is the table name in the databasename/tablename format
@param[in] path_in expected filepath, usually read from dictionary
@param[out] err DB_SUCCESS or error code
@param id tablespace identifier
@param flags expected FSP_SPACE_FLAGS
@param validate how to validate files
@param name the table name in databasename/tablename format
@param path_in expected filepath, usually read from dictionary
@param err DB_SUCCESS or error code
@return tablespace
@retval NULL if the tablespace could not be opened */
fil_space_t*
fil_ibd_open(
unsigned validate,
fil_type_t purpose,
ulint id,
ulint flags,
fil_space_t::name_type name,
const char* path_in,
dberr_t* err = NULL)
MY_ATTRIBUTE((warn_unused_result));
@retval nullptr if the tablespace could not be opened */
fil_space_t *fil_ibd_open(ulint id, ulint flags,
fil_space_t::validate validate,
fil_space_t::name_type name,
const char *path_in, dberr_t *err= nullptr) noexcept;
enum fil_load_status {
/** The tablespace file(s) were found and valid. */

View file

@ -93,9 +93,9 @@ void recv_sys_justify_left_parsing_buf();
@param[in] len length of name, in bytes
@param[in] new_name new file name (NULL if not rename)
@param[in] new_len length of new_name, in bytes (0 if NULL) */
extern void (*log_file_op)(ulint space_id, int type,
const byte* name, ulint len,
const byte* new_name, ulint new_len);
extern void (*log_file_op)(uint32_t space_id, int type,
const byte* name, size_t len,
const byte* new_name, size_t new_len);
/** Report an operation which does undo log tablespace truncation
during backup
@ -104,7 +104,7 @@ extern void (*undo_space_trunc)(uint32_t space_id);
/** Report an operation which does INIT_PAGE for page0 during backup.
@param space_id tablespace identifier */
extern void (*first_page_init)(ulint space_id);
extern void (*first_page_init)(uint32_t space_id);
/** Stored redo log record */
struct log_rec_t

View file

@ -598,10 +598,10 @@ struct file_name_t {
/** Map of dirty tablespaces during recovery */
typedef std::map<
ulint,
uint32_t,
file_name_t,
std::less<ulint>,
ut_allocator<std::pair<const ulint, file_name_t> > > recv_spaces_t;
ut_allocator<std::pair<const uint32_t, file_name_t> > > recv_spaces_t;
static recv_spaces_t recv_spaces;
@ -820,8 +820,8 @@ processed:
if (crypt_data && !fil_crypt_check(crypt_data, name.c_str()))
return nullptr;
mysql_mutex_lock(&fil_system.mutex);
fil_space_t *space= fil_space_t::create(it->first, flags,
FIL_TYPE_TABLESPACE, crypt_data);
fil_space_t *space= fil_space_t::create(it->first, flags, false,
crypt_data);
ut_ad(space);
const char *filename= name.c_str();
if (srv_operation == SRV_OPERATION_RESTORE)
@ -939,13 +939,13 @@ deferred_spaces;
@param[in] len length of name, in bytes
@param[in] new_name new file name (NULL if not rename)
@param[in] new_len length of new_name, in bytes (0 if NULL) */
void (*log_file_op)(ulint space_id, int type,
const byte* name, ulint len,
const byte* new_name, ulint new_len);
void (*log_file_op)(uint32_t space_id, int type,
const byte* name, size_t len,
const byte* new_name, size_t new_len);
void (*undo_space_trunc)(uint32_t space_id);
void (*first_page_init)(ulint space_id);
void (*first_page_init)(uint32_t space_id);
/** Information about initializing page contents during redo log processing.
FIXME: Rely on recv_sys.pages! */
@ -4203,7 +4203,7 @@ recv_validate_tablespace(bool rescan, bool& missing_tablespace)
for (recv_sys_t::map::iterator p = recv_sys.pages.begin();
p != recv_sys.pages.end();) {
ut_ad(!p->second.log.empty());
const ulint space = p->first.space();
const uint32_t space = p->first.space();
if (is_predefined_tablespace(space)) {
next:
p++;
@ -4213,7 +4213,7 @@ next:
recv_spaces_t::iterator i = recv_spaces.find(space);
ut_ad(i != recv_spaces.end());
if (deferred_spaces.find(static_cast<uint32_t>(space))) {
if (deferred_spaces.find(space)) {
/* Skip redo logs belonging to
incomplete tablespaces */
goto next;

View file

@ -488,8 +488,7 @@ mtr_t::x_lock_space(ulint space_id)
} else {
space = fil_space_get(space_id);
ut_ad(m_log_mode != MTR_LOG_NO_REDO
|| space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT);
|| space->is_temporary() || space->is_being_imported());
}
ut_ad(space);
@ -502,9 +501,6 @@ mtr_t::x_lock_space(ulint space_id)
@param space tablespace */
void mtr_t::x_lock_space(fil_space_t *space)
{
ut_ad(space->purpose == FIL_TYPE_TEMPORARY ||
space->purpose == FIL_TYPE_IMPORT ||
space->purpose == FIL_TYPE_TABLESPACE);
if (!memo_contains(*space))
{
memo_push(space, MTR_MEMO_SPACE_X_LOCK);

View file

@ -3947,13 +3947,19 @@ void fil_node_t::find_metadata(IF_WIN(,bool create)) noexcept
punch_hole= 2;
else
punch_hole= IF_WIN(, !create ||) os_is_sparse_file_supported(file);
if (space->purpose != FIL_TYPE_TABLESPACE)
/* For temporary tablespace or during IMPORT TABLESPACE, we
disable neighbour flushing and do not care about atomicity. */
if (space->is_temporary())
{
/* For temporary tablespace or during IMPORT TABLESPACE, we
disable neighbour flushing and do not care about atomicity. */
on_ssd= true;
atomic_write= true;
if (space->purpose == FIL_TYPE_TEMPORARY || !space->is_compressed())
return;
}
if (space->is_being_imported())
{
on_ssd= true;
atomic_write= true;
if (!space->is_compressed())
return;
}
#ifdef _WIN32

View file

@ -4841,11 +4841,10 @@ import_error:
we will not be writing any redo log for it before we have invoked
fil_space_t::set_imported() to declare it a persistent tablespace. */
ulint fsp_flags = dict_tf_to_fsp_flags(table->flags);
table->space = fil_ibd_open(
2, FIL_TYPE_IMPORT, table->space_id,
fsp_flags, name, filepath, &err);
table->space = fil_ibd_open(table->space_id,
dict_tf_to_fsp_flags(table->flags),
fil_space_t::VALIDATE_IMPORT,
name, filepath, &err);
ut_ad((table->space == NULL) == (err != DB_SUCCESS));
DBUG_EXECUTE_IF("ib_import_open_tablespace_failure",
@ -4947,8 +4946,6 @@ import_error:
}
ib::info() << "Phase IV - Flush complete";
/* Set tablespace purpose as FIL_TYPE_TABLESPACE,
so that rollback can go ahead smoothly */
table->space->set_imported();
err = lock_sys_tables(trx);

View file

@ -575,9 +575,9 @@ err_exit:
fil_set_max_space_id_if_bigger(space_id);
mysql_mutex_lock(&fil_system.mutex);
fil_space_t *space= fil_space_t::create(space_id, fsp_flags,
FIL_TYPE_TABLESPACE, nullptr,
FIL_ENCRYPTION_DEFAULT, true);
fil_space_t *space= fil_space_t::create(uint32_t(space_id),
fsp_flags, false, nullptr,
FIL_ENCRYPTION_DEFAULT, true);
ut_ad(space);
fil_node_t *file= space->add(name, fh, 0, false, true);

View file

@ -238,7 +238,8 @@ static trx_rseg_t *trx_rseg_create(ulint space_id)
if (fil_space_t *space= mtr.x_lock_space(space_id))
{
ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
ut_ad(!space->is_temporary());
ut_ad(!space->is_being_imported());
if (buf_block_t *sys_header= trx_sysf_get(&mtr))
{
ulint rseg_id= trx_sys_rseg_find_free(sys_header);