diff options
31 files changed, 578 insertions, 770 deletions
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 7aa20b8700e..4f9e493b347 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -93,7 +93,6 @@ xb_fil_node_close_file( mutex_enter(&fil_system.mutex); ut_ad(node); - ut_a(node->n_pending_flushes == 0); ut_a(!node->being_extended); if (!node->is_open()) { @@ -406,7 +405,7 @@ xb_fil_cur_read( retry_count = 10; ret = XB_FIL_CUR_SUCCESS; - fil_space_t *space = fil_space_t::get_for_io(cursor->space_id); + fil_space_t *space = fil_space_t::get(cursor->space_id); if (!space) { return XB_FIL_CUR_ERROR; @@ -455,7 +454,7 @@ read_retry: posix_fadvise(cursor->file, offset, to_read, POSIX_FADV_DONTNEED); func_exit: - space->release_for_io(); + space->release(); return(ret); } diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 39025862276..c05677b8810 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3094,10 +3094,10 @@ xb_load_single_table_tablespace( ut_a(space != NULL); - space->add(file->filepath(), OS_FILE_CLOSED, 0, false, false); - /* by opening the tablespace we forcing node and space objects - in the cache to be populated with fields from space header */ - space->get_size(); + space->add(file->filepath(), file->detach(), 0, false, false); + mutex_enter(&fil_system.mutex); + space->read_page0(); + mutex_exit(&fil_system.mutex); if (srv_operation == SRV_OPERATION_RESTORE_DELTA || xb_close_files) { @@ -3402,7 +3402,7 @@ xb_load_tablespaces() /** Destroy the tablespace memory cache. */ static void xb_data_files_close() { - fil_close_all_files(); + fil_space_t::close_all(); buf_dblwr.close(); } diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index f602e0d19a2..ee1bc20e1c9 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -60,12 +60,10 @@ PageBulk::init() alloc_mtr.start(); m_index->set_modified(alloc_mtr); - ulint n_reserved; - bool success; - success = fsp_reserve_free_extents(&n_reserved, - m_index->table->space, - 1, FSP_NORMAL, &alloc_mtr); - if (!success) { + uint32_t n_reserved; + if (!fsp_reserve_free_extents(&n_reserved, + m_index->table->space, + 1, FSP_NORMAL, &alloc_mtr)) { alloc_mtr.commit(); m_mtr.commit(); return(DB_OUT_OF_FILE_SPACE); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index c280ed555fe..fdb56e34d7e 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3318,20 +3318,16 @@ static void btr_cur_prefetch_siblings(const buf_block_t *block, uint32_t prev= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_PREV)); uint32_t next= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_NEXT)); - if (prev != FIL_NULL) - { - ut_a(index->table->space->acquire_for_io()); + if (prev == FIL_NULL); + else if (index->table->space->acquire()) buf_read_page_background(index->table->space, page_id_t(block->page.id().space(), prev), block->zip_size(), false); - } - if (next != FIL_NULL) - { - ut_a(index->table->space->acquire_for_io()); + if (next == FIL_NULL); + else if (index->table->space->acquire()) buf_read_page_background(index->table->space, page_id_t(block->page.id().space(), next), block->zip_size(), false); - } } /*************************************************************//** @@ -3679,7 +3675,7 @@ btr_cur_pessimistic_insert( dberr_t err; bool inherit = false; bool success; - ulint n_reserved = 0; + uint32_t n_reserved = 0; ut_ad(dtuple_check_typed(entry)); ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG))); @@ -3711,7 +3707,7 @@ btr_cur_pessimistic_insert( of the index tree, so that the insert will not fail because of lack of space */ - ulint n_extents = cursor->tree_height / 16 + 3; + uint32_t n_extents = uint32_t(cursor->tree_height / 16 + 3); success = fsp_reserve_free_extents(&n_reserved, index->table->space, @@ -4878,8 +4874,8 @@ btr_cur_pessimistic_update( dberr_t err; dberr_t optim_err; roll_ptr_t roll_ptr; - ibool was_first; - ulint n_reserved = 0; + bool was_first; + uint32_t n_reserved = 0; *offsets = NULL; *big_rec = NULL; @@ -5041,7 +5037,7 @@ btr_cur_pessimistic_update( of the index tree, so that the update will not fail because of lack of space */ - ulint n_extents = cursor->tree_height / 16 + 3; + uint32_t n_extents = uint32_t(cursor->tree_height / 16 + 3); if (!fsp_reserve_free_extents( &n_reserved, index->table->space, n_extents, @@ -5643,7 +5639,7 @@ btr_cur_pessimistic_delete( page_zip_des_t* page_zip; dict_index_t* index; rec_t* rec; - ulint n_reserved = 0; + uint32_t n_reserved = 0; bool success; ibool ret = FALSE; mem_heap_t* heap; @@ -5672,7 +5668,7 @@ btr_cur_pessimistic_delete( of the index tree, so that the node pointer updates will not fail because of lack of space */ - ulint n_extents = cursor->tree_height / 32 + 1; + uint32_t n_extents = uint32_t(cursor->tree_height / 32 + 1); success = fsp_reserve_free_extents(&n_reserved, index->table->space, @@ -7315,7 +7311,7 @@ btr_store_big_rec_extern_fields( for (ulint blob_npages = 0;; ++blob_npages) { buf_block_t* block; const ulint commit_freq = 4; - ulint r_extents; + uint32_t r_extents; ut_ad(page_align(field_ref) == page_align(rec)); @@ -7588,7 +7584,7 @@ static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read) if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB)) return; /* FIXME: take the tablespace as a parameter */ - if (fil_space_t *space= fil_space_acquire_silent(block.page.id().space())) + if (fil_space_t *space= fil_space_t::get(block.page.id().space())) { /* Old versions of InnoDB did not initialize FIL_PAGE_TYPE on BLOB pages. Do not print anything about the type mismatch when reading diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 2046ffd4273..2cdd36a8b60 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -415,7 +415,7 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame) static bool buf_page_decrypt_after_read(buf_page_t *bpage, const fil_node_t &node) { - ut_ad(node.space->pending_io()); + ut_ad(node.space->referenced()); ut_ad(node.space->id == bpage->id().space()); const auto flags = node.space->flags; @@ -475,7 +475,7 @@ decompress_with_slot: slot->release(); ut_ad(!write_size || fil_page_type_validate(node.space, dst_frame)); - ut_ad(node.space->pending_io()); + ut_ad(node.space->referenced()); return write_size != 0; } @@ -516,7 +516,7 @@ decrypt_failed: goto decompress; } - ut_ad(node.space->pending_io()); + ut_ad(node.space->referenced()); return true; } #endif /* !UNIV_INNOCHECKSUM */ @@ -2768,7 +2768,7 @@ buf_zip_decompress( ulint size = page_zip_get_size(&block->page.zip); /* The tablespace will not be found if this function is called during IMPORT. */ - fil_space_t* space= fil_space_t::get_for_io(block->page.id().space()); + fil_space_t* space= fil_space_t::get(block->page.id().space()); const unsigned key_version = mach_read_from_4( frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); fil_space_crypt_t* crypt_data = space ? space->crypt_data : NULL; @@ -2805,7 +2805,7 @@ buf_zip_decompress( if (page_zip_decompress(&block->page.zip, block->frame, TRUE)) { if (space) { - space->release_for_io(); + space->release(); } return(TRUE); } @@ -2824,7 +2824,7 @@ buf_zip_decompress( /* Copy to uncompressed storage. */ memcpy(block->frame, frame, block->zip_size()); if (space) { - space->release_for_io(); + space->release(); } return(TRUE); @@ -2848,7 +2848,7 @@ err_exit: dict_set_corrupted_by_space(space); } - space->release_for_io(); + space->release(); } return(FALSE); @@ -3160,10 +3160,10 @@ lookup: asserting. */ if (page_id.space() == TRX_SYS_SPACE) { } else if (page_id.space() == SRV_TMP_SPACE_ID) { - } else if (fil_space_t* space= fil_space_t::get_for_io( + } else if (fil_space_t* space= fil_space_t::get( page_id.space())) { bool set = dict_set_corrupted_by_space(space); - space->release_for_io(); + space->release(); if (set) { return NULL; } @@ -3374,8 +3374,7 @@ re_evict: if (mode != BUF_GET_IF_IN_POOL && mode != BUF_GET_IF_IN_POOL_OR_WATCH) { } else if (!ibuf_debug) { - } else if (fil_space_t* space - = fil_space_t::get_for_io(page_id.space())) { + } else if (fil_space_t* space = fil_space_t::get(page_id.space())) { /* Try to evict the block from the buffer pool, to use the insert buffer (change buffer) as much as possible. */ @@ -3386,7 +3385,7 @@ re_evict: /* Blocks cannot be relocated or enter or exit the buf_pool while we are holding the buf_pool.mutex. */ const bool evicted = buf_LRU_free_page(&fix_block->page, true); - space->release_for_io(); + space->release(); if (evicted) { hash_lock = buf_pool.page_hash.lock_get(fold); @@ -4108,7 +4107,7 @@ after decryption normal page checksum does not match. static dberr_t buf_page_check_corrupt(buf_page_t *bpage, const fil_node_t &node) { - ut_ad(node.space->pending_io()); + ut_ad(node.space->referenced()); byte* dst_frame = (bpage->zip.data) ? bpage->zip.data : ((buf_block_t*) bpage)->frame; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 6b1a32d8930..eb460af2de2 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -363,7 +363,7 @@ void buf_dblwr_t::recover() continue; } - fil_space_t *space= fil_space_t::get_for_io(space_id); + fil_space_t *space= fil_space_t::get(space_id); if (!space) /* The tablespace that this page once belonged to does not exist */ @@ -379,7 +379,7 @@ void buf_dblwr_t::recover() << " is beyond the end of tablespace " << space->name << " (" << space->size << " pages)"; next_page: - space->release_for_io(); + space->release(); continue; } @@ -420,7 +420,7 @@ next_page: /* Write the good page from the doublewrite buffer to the intended position. */ - space->reacquire_for_io(); + space->reacquire(); fio= space->io(IORequestWrite, os_offset_t{page_id.page_no()} * physical_size, physical_size, page); @@ -506,10 +506,10 @@ static void buf_dblwr_check_page_lsn(const page_t* page, const fil_space_t& s) static void buf_dblwr_check_page_lsn(const buf_page_t &b, const byte *page) { - if (fil_space_t *space= fil_space_t::get_for_io(b.id().space())) + if (fil_space_t *space= fil_space_t::get(b.id().space())) { buf_dblwr_check_page_lsn(page, *space); - space->release_for_io(); + space->release(); } } @@ -583,7 +583,7 @@ bool buf_dblwr_t::flush_buffered_writes(const ulint size) } #endif /* UNIV_DEBUG */ /* Write out the first block of the doublewrite buffer */ - ut_a(fil_system.sys_space->acquire_for_io()); + ut_a(fil_system.sys_space->acquire()); fil_system.sys_space->io(IORequestWrite, os_offset_t{block1.page_no()} << srv_page_size_shift, @@ -593,7 +593,7 @@ bool buf_dblwr_t::flush_buffered_writes(const ulint size) if (old_first_free > size) { /* Write out the second block of the doublewrite buffer. */ - ut_a(fil_system.sys_space->acquire_for_io()); + ut_a(fil_system.sys_space->acquire()); fil_system.sys_space->io(IORequestWrite, os_offset_t{block2.page_no()} << srv_page_size_shift, @@ -687,7 +687,7 @@ void buf_dblwr_t::add_to_batch(fil_space_t *space, const IORequest &request, ut_ad(request.bpage); ut_ad(request.bpage->in_file()); ut_ad(space->id == request.bpage->id().space()); - ut_ad(space->pending_io()); + ut_ad(space->referenced()); ut_ad(!srv_read_only_mode); const ulint buf_size= 2 * block_size(); diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 19a9e09e4a1..c62c0112e92 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -621,19 +621,11 @@ buf_load() ulint last_check_time = 0; ulint last_activity_cnt = 0; - /* Avoid calling the expensive fil_space_acquire_silent() for each + /* Avoid calling the expensive fil_space_t::get() for each page within the same tablespace. dump[] is sorted by (space, page), so all pages from a given tablespace are consecutive. */ ulint cur_space_id = dump[0].space(); - fil_space_t* space = fil_space_acquire_silent(cur_space_id); - if (space) { - bool ok = space->acquire_for_io(); - space->release(); - if (!ok) { - space = nullptr; - } - } - + fil_space_t* space = fil_space_t::get(cur_space_id); ulint zip_size = space ? space->zip_size() : 0; PSI_stage_progress* pfs_stage_progress __attribute__((unused)) @@ -653,24 +645,16 @@ buf_load() if (this_space_id != cur_space_id) { if (space) { - space->release_for_io(); + space->release(); } cur_space_id = this_space_id; - space = fil_space_acquire_silent(cur_space_id); + space = fil_space_t::get(cur_space_id); if (!space) { continue; } - bool ok = space->acquire_for_io(); - space->release(); - - if (!ok) { - space = nullptr; - continue; - } - zip_size = space->zip_size(); } @@ -684,17 +668,17 @@ buf_load() } if (space->is_stopping()) { - space->release_for_io(); + space->release(); space = nullptr; continue; } - space->reacquire_for_io(); + space->reacquire(); buf_read_page_background(space, dump[i], zip_size, true); if (buf_load_abort_flag) { if (space) { - space->release_for_io(); + space->release(); } buf_load_abort_flag = false; ut_free(dump); @@ -722,7 +706,7 @@ buf_load() } if (space) { - space->release_for_io(); + space->release(); } ut_free(dump); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 25523ab53f1..f671aadeb4e 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -786,7 +786,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) (space == fil_system.temp_space)); ut_ad(space->purpose == FIL_TYPE_TABLESPACE || space->atomic_write_supported); - ut_ad(space->pending_io()); + ut_ad(space->referenced()); rw_lock_t *rw_lock; @@ -854,7 +854,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) buf_release_freed_page(&block->page); else { - space->reacquire_for_io(); + space->reacquire(); ut_ad(status == buf_page_t::NORMAL || status == buf_page_t::INIT_ON_FLUSH); size_t size, orig_size; IORequest::Type type= lru ? IORequest::WRITE_LRU : IORequest::WRITE_ASYNC; @@ -1029,7 +1029,7 @@ static void buf_flush_freed_pages(fil_space_t *space) if (punch_hole) { - space->reacquire_for_io(); + space->reacquire(); space->io(IORequest(IORequest::PUNCH_RANGE), os_offset_t{range.first} * physical_size, (range.last - range.first + 1) * physical_size, @@ -1039,7 +1039,7 @@ static void buf_flush_freed_pages(fil_space_t *space) { for (os_offset_t i= range.first; i <= range.last; i++) { - space->reacquire_for_io(); + space->reacquire(); space->io(IORequest(IORequest::WRITE_ASYNC), i * physical_size, physical_size, const_cast<byte*>(field_ref_zero)); @@ -1170,7 +1170,7 @@ static ulint buf_free_from_unzip_LRU_list_batch(ulint max) @retval nullptr if the pages for this tablespace should be discarded */ static fil_space_t *buf_flush_space(const uint32_t id) { - fil_space_t *space= fil_space_t::get_for_io(id); + fil_space_t *space= fil_space_t::get(id); if (space) buf_flush_freed_pages(space); return space; @@ -1261,7 +1261,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) if (last_space_id != space_id) { if (space) - space->release_for_io(); + space->release(); space= buf_flush_space(space_id); last_space_id= space_id; } @@ -1270,7 +1270,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) } else if (space->is_stopping()) { - space->release_for_io(); + space->release(); space= nullptr; } @@ -1298,7 +1298,7 @@ reacquire_mutex: buf_pool.lru_hp.set(nullptr); if (space) - space->release_for_io(); + space->release(); /* We keep track of all flushes happening as part of LRU flush. When estimating the desired rate at which flush_list should be flushed, @@ -1393,7 +1393,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) if (last_space_id != space_id) { if (space) - space->release_for_io(); + space->release(); space= buf_flush_space(space_id); last_space_id= space_id; } @@ -1402,7 +1402,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) } else if (space->is_stopping()) { - space->release_for_io(); + space->release(); space= nullptr; } @@ -1431,7 +1431,7 @@ reacquire_mutex: mysql_mutex_unlock(&buf_pool.flush_list_mutex); if (space) - space->release_for_io(); + space->release(); if (scanned) MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BATCH_SCANNED, diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index daea53ec130..2f59f1ae4d5 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -288,7 +288,7 @@ buf_read_page_low( << page_id; ut_ad(0); nothing_read: - space->release_for_io(); + space->release(); return false; } @@ -358,7 +358,7 @@ nothing_read: /* The i/o was already completed in space->io() */ *err = buf_page_read_complete(bpage, *fio.node); - space->release_for_io(); + space->release(); if (*err != DB_SUCCESS) { return false; @@ -402,7 +402,7 @@ buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) if (buf_pool.n_pend_reads > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT) return 0; - fil_space_t* space= fil_space_acquire(page_id.space()); + fil_space_t* space= fil_space_t::get(page_id.space()); if (!space) return 0; @@ -431,7 +431,7 @@ no_read_ahead: return 0; read_ahead: - if (!space->acquire_for_io()) + if (!space->acquire_if_not_stopped()) goto no_read_ahead; /* Read all the suitable blocks within the area */ @@ -444,7 +444,7 @@ read_ahead: if (space->is_stopping()) break; dberr_t err; - space->reacquire_for_io(); + space->reacquire(); if (buf_read_page_low(&err, space, false, ibuf_mode, i, zip_size, false)) count++; } @@ -453,7 +453,6 @@ read_ahead: DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u", count, space->chain.start->name, low.page_no())); - space->release_for_io(); space->release(); /* Read ahead is considered one I/O operation for the purpose of @@ -478,22 +477,13 @@ after decryption normal page checksum does not match. @retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ dberr_t buf_read_page(const page_id_t page_id, ulint zip_size) { - fil_space_t *space= fil_space_acquire(page_id.space()); + fil_space_t *space= fil_space_t::get(page_id.space()); if (!space) { ib::info() << "trying to read page " << page_id << " in nonexisting or being-dropped tablespace"; return DB_TABLESPACE_DELETED; } - else if (!space->acquire_for_io()) - { - ib::warn() << "unable to read " << page_id << " from tablespace " - << space->name; - space->release(); - return DB_PAGE_CORRUPTED; - } - - space->release(); dberr_t err; if (buf_read_page_low(&err, space, true, BUF_READ_ANY_PAGE, @@ -607,22 +597,15 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) read-ahead, as that could break the ibuf page access order */ return 0; - fil_space_t *space= fil_space_acquire(page_id.space()); + fil_space_t *space= fil_space_t::get(page_id.space()); if (!space) return 0; - else - { - bool ok= space->acquire_for_io(); - space->release(); - if (!ok) - return 0; - } if (high_1.page_no() > space->last_page_number()) { /* The area is not whole. */ fail: - space->release_for_io(); + space->release(); return 0; } @@ -721,7 +704,7 @@ failed: if (space->is_stopping()) break; dberr_t err; - space->reacquire_for_io(); + space->reacquire(); count+= buf_read_page_low(&err, space, false, ibuf_mode, new_low, zip_size, false); } @@ -730,7 +713,7 @@ failed: DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u", count, space->chain.start->name, new_low.page_no())); - space->release_for_io(); + space->release(); /* Read ahead is considered one I/O operation for the purpose of LRU policy decision. */ @@ -747,7 +730,7 @@ highest page number the last in the array @param[in] n number of page numbers in the array */ void buf_read_recv_pages(ulint space_id, const uint32_t* page_nos, ulint n) { - fil_space_t* space = fil_space_t::get_for_io(space_id); + fil_space_t* space = fil_space_t::get(space_id); if (!space) { /* The tablespace is missing or unreadable: do nothing */ @@ -784,7 +767,7 @@ void buf_read_recv_pages(ulint space_id, const uint32_t* page_nos, ulint n) } dberr_t err; - space->reacquire_for_io(); + space->reacquire(); buf_read_page_low(&err, space, false, BUF_READ_ANY_PAGE, cur_page_id, zip_size, true); @@ -798,5 +781,5 @@ void buf_read_recv_pages(ulint space_id, const uint32_t* page_nos, ulint n) DBUG_PRINT("ib_buf", ("recovery read (%u pages) for %s", n, space->chain.start->name)); - space->release_for_io(); + space->release(); } diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index fb3247ecdcf..55e3191c228 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -948,7 +948,7 @@ void dict_drop_index_tree(btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr) ut_ad(len == 8); - if (fil_space_t* s = fil_space_acquire_silent(space_id)) { + if (fil_space_t* s = fil_space_t::get(space_id)) { /* Ensure that the tablespace file exists in order to avoid a crash in buf_page_get_gen(). */ if (root_page_no < s->get_size()) { diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 52b77fd93a5..a4a660be584 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -884,7 +884,7 @@ is_unaccessible: return nullptr; } - if (!fil_table_accessible(table)) + if (!table->is_accessible()) goto is_unaccessible; size_t db1_len, tbl1_len; diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 0b2e28b6476..bd7ae83b53a 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -358,7 +358,7 @@ next_table_id: ut_ad(!table->is_temporary()); - if (!fil_table_accessible(table)) { + if (!table->is_accessible()) { dict_table_close(table, TRUE, FALSE); mutex_exit(&dict_sys.mutex); goto next_table_id; diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index e73337a3bdd..73f87173485 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -633,7 +633,7 @@ byte* fil_space_encrypt( return (src_frame); } - ut_ad(space->pending_io()); + ut_ad(space->referenced()); return fil_encrypt_buf(space->crypt_data, space->id, offset, src_frame, space->zip_size(), @@ -846,7 +846,7 @@ fil_space_decrypt( const ulint physical_size = space->physical_size(); ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted()); - ut_ad(space->pending_io()); + ut_ad(space->referenced()); bool encrypted = fil_space_decrypt(space->id, space->crypt_data, tmp_frame, physical_size, @@ -1008,8 +1008,6 @@ fil_crypt_read_crypt_data(fil_space_t* space) @return true if a recheck of tablespace is needed by encryption thread. */ static bool fil_crypt_start_encrypting_space(fil_space_t* space) { - bool recheck = false; - mutex_enter(&fil_crypt_threads_mutex); fil_space_crypt_t *crypt_data = space->crypt_data; @@ -1021,12 +1019,9 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space) return false; } - if (crypt_data != NULL || fil_crypt_start_converting) { - /* someone beat us to it */ - if (fil_crypt_start_converting) { - recheck = true; - } + const bool recheck = fil_crypt_start_converting; + if (recheck || crypt_data || space->is_stopping()) { mutex_exit(&fil_crypt_threads_mutex); return recheck; } @@ -1045,36 +1040,38 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space) return false; } - crypt_data->type = CRYPT_SCHEME_UNENCRYPTED; - crypt_data->min_key_version = 0; // all pages are unencrypted - crypt_data->rotate_state.start_time = time(0); - crypt_data->rotate_state.starting = true; - crypt_data->rotate_state.active_threads = 1; - - mutex_enter(&fil_system.mutex); - space->crypt_data = crypt_data; - mutex_exit(&fil_system.mutex); - fil_crypt_start_converting = true; mutex_exit(&fil_crypt_threads_mutex); - do - { - mtr_t mtr; - mtr.start(); - mtr.set_named_space(space); + mtr_t mtr; + mtr.start(); - /* 2 - get page 0 */ - dberr_t err = DB_SUCCESS; - buf_block_t* block = buf_page_get_gen( - page_id_t(space->id, 0), space->zip_size(), - RW_X_LATCH, NULL, BUF_GET, - __FILE__, __LINE__, - &mtr, &err); + /* 2 - get page 0 */ + dberr_t err = DB_SUCCESS; + if (buf_block_t* block = buf_page_get_gen( + page_id_t(space->id, 0), space->zip_size(), + RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, + __FILE__, __LINE__, &mtr, &err)) { + + crypt_data->type = CRYPT_SCHEME_1; + crypt_data->min_key_version = 0; // all pages are unencrypted + crypt_data->rotate_state.start_time = time(0); + crypt_data->rotate_state.starting = true; + crypt_data->rotate_state.active_threads = 1; + + mutex_enter(&fil_system.mutex); + const bool stopping = space->is_stopping(); + if (!stopping) { + space->crypt_data = crypt_data; + } + mutex_exit(&fil_system.mutex); + if (stopping) { + goto abort; + } /* 3 - write crypt data to page 0 */ - crypt_data->type = CRYPT_SCHEME_1; + mtr.set_named_space(space); crypt_data->write_page0(block, &mtr); mtr.commit(); @@ -1094,19 +1091,18 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space) mutex_exit(&crypt_data->mutex); mutex_exit(&fil_crypt_threads_mutex); - return recheck; - } while (0); - - mutex_enter(&crypt_data->mutex); - ut_a(crypt_data->rotate_state.active_threads == 1); - crypt_data->rotate_state.active_threads = 0; - mutex_exit(&crypt_data->mutex); + return false; + } +abort: + mtr.commit(); mutex_enter(&fil_crypt_threads_mutex); fil_crypt_start_converting = false; mutex_exit(&fil_crypt_threads_mutex); - return recheck; + crypt_data->~fil_space_crypt_t(); + ut_free(crypt_data); + return false; } /** State of a rotation thread */ @@ -1479,7 +1475,7 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, while (it != end) { space= &*it; - if (space->acquire()) + if (space->acquire_if_not_stopped(true)) return space; while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); } @@ -1487,44 +1483,41 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, return NULL; } -/** Return the next tablespace. -@param space previous tablespace (NULL to start from the beginning) +/** Determine the next tablespace for encryption key rotation. +@param space current tablespace (nullptr to start from the beginning) @param recheck whether the removal condition needs to be rechecked after -the encryption parameters were changed +encryption parameters were changed @param encrypt expected state of innodb_encrypt_tables -@return pointer to the next tablespace (with n_pending_ops incremented) -@retval NULL if this was the last */ -static fil_space_t *fil_space_next(fil_space_t *space, bool recheck, - bool encrypt) +@return the next tablespace +@retval nullptr upon reaching the end of the iteration */ +inline fil_space_t *fil_space_t::next(fil_space_t *space, bool recheck, + bool encrypt) { mutex_enter(&fil_system.mutex); if (!srv_fil_crypt_rotate_key_age) space= fil_system.keyrotate_next(space, recheck, encrypt); - else if (!space) - { - space= UT_LIST_GET_FIRST(fil_system.space_list); - /* We can trust that space is not NULL because at least the - system tablespace is always present and loaded first. */ - if (!space->acquire()) - goto next; - } else { - /* Move on to the next fil_space_t */ - space->release(); -next: - space= UT_LIST_GET_NEXT(space_list, space); - - /* Skip abnormal tablespaces or those that are being created by - fil_ibd_create(), or being dropped. */ - while (space && - (UT_LIST_GET_LEN(space->chain) == 0 || - space->is_stopping() || space->purpose != FIL_TYPE_TABLESPACE)) + if (!space) + space= UT_LIST_GET_FIRST(fil_system.space_list); + else + { + /* Move on to the next fil_space_t */ + space->release(); space= UT_LIST_GET_NEXT(space_list, space); + } - if (space && !space->acquire()) - goto next; + for (; space; space= UT_LIST_GET_NEXT(space_list, space)) + { + if (space->purpose != FIL_TYPE_TABLESPACE) + continue; + const uint32_t n= space->acquire_low(); + if (UNIV_LIKELY(!(n & (STOPPING | CLOSING)))) + break; + if (!(n & STOPPING) && space->prepare(true)) + break; + } } mutex_exit(&fil_system.mutex); @@ -1568,8 +1561,8 @@ static bool fil_crypt_find_space_to_rotate( state->space = NULL; } - state->space = fil_space_next(state->space, *recheck, - key_state->key_version != 0); + state->space = fil_space_t::next(state->space, *recheck, + key_state->key_version != 0); while (!state->should_shutdown() && state->space) { /* If there is no crypt data and we have not yet read @@ -1587,8 +1580,8 @@ static bool fil_crypt_find_space_to_rotate( return true; } - state->space = fil_space_next(state->space, *recheck, - key_state->key_version != 0); + state->space = fil_space_t::next(state->space, *recheck, + key_state->key_version != 0); } if (state->space) { @@ -2000,7 +1993,7 @@ fil_crypt_flush_space( if (buf_block_t* block = buf_page_get_gen( page_id_t(space->id, 0), space->zip_size(), - RW_X_LATCH, NULL, BUF_GET, + RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err)) { mtr.set_named_space(space); crypt_data->write_page0(block, &mtr); @@ -2240,15 +2233,12 @@ static void fil_crypt_rotation_list_fill() if (space->purpose != FIL_TYPE_TABLESPACE || space->is_in_rotation_list || UT_LIST_GET_LEN(space->chain) == 0 - || !space->acquire()) { + || !space->acquire_if_not_stopped(true)) { continue; } /* Ensure that crypt_data has been initialized. */ - if (!space->get_size()) { - /* Page 0 was not loaded. Skip this tablespace. */ - goto next; - } + ut_ad(space->size); /* Skip ENCRYPTION!=DEFAULT tablespaces. */ if (space->crypt_data diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index ad9d2828467..1829bec8a73 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -64,10 +64,10 @@ inline bool fil_is_user_tablespace_id(ulint space_id) !srv_is_undo_tablespace(space_id); } -/** Try to close a file. -@return true if success, false if should retry later -@param print_info if true, prints information why it cannot close a file */ -static bool fil_try_to_close_file(bool print_info) +/** Try to close a file to adhere to the innodb_open_files limit. +@param print_info whether to diagnose why a file cannot be closed +@return whether a file was closed */ +bool fil_space_t::try_to_close(bool print_info) { ut_ad(mutex_own(&fil_system.mutex)); for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space; @@ -94,27 +94,15 @@ static bool fil_try_to_close_file(bool print_info) if (!node->is_open()) continue; - if (auto n= space->set_closing()) + if (const auto n= space->set_closing()) { if (print_info) ib::info() << "Cannot close file " << node->name - << " because of " << n << " pending operations"; - continue; - } - - if (auto n= node->n_pending_flushes) - { - if (print_info) - ib::info() << "Cannot close file " << node->name - << ", because n_pending_flushes " << n; - continue; - } - - if (node->needs_flush) - { - if (print_info) - ib::info() << "Cannot close file " << node->name - << ", because is should be flushed first"; + << " because of " + << (n & PENDING) + << ((n & NEEDS_FSYNC) + ? " pending operations and pending fsync" + : " pending operations"); continue; } @@ -210,7 +198,7 @@ const char* fil_path_to_mysql_datadir; const char* dot_ext[] = { "", ".ibd", ".isl", ".cfg" }; /** Number of pending tablespace flushes */ -ulint fil_n_pending_tablespace_flushes = 0; +Atomic_counter<ulint> fil_n_pending_tablespace_flushes; /** The tablespace memory cache. This variable is NULL before the module is initialized. */ @@ -267,8 +255,7 @@ The caller should hold an InnoDB table lock or a MDL that prevents the tablespace from being dropped during the operation, or the caller should be in single-threaded crash recovery mode (no user connections that could drop tablespaces). -If this is not the case, fil_space_acquire() and fil_space_t::release() -should be used instead. +Normally, fil_space_t::get() should be used instead. @param[in] id tablespace ID @return tablespace, or NULL if not found */ fil_space_t* @@ -281,30 +268,6 @@ fil_space_get( return(space); } -/**********************************************************************//** -Checks if all the file nodes in a space are flushed. -@return true if all are flushed */ -static -bool -fil_space_is_flushed( -/*=================*/ - fil_space_t* space) /*!< in: space */ -{ - ut_ad(mutex_own(&fil_system.mutex)); - - for (const fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - node != NULL; - node = UT_LIST_GET_NEXT(chain, node)) { - - if (node->needs_flush) { - ut_ad(srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC); - return(false); - } - } - - return(true); -} - /** Validate the compression algorithm for full crc32 format. @param[in] space tablespace object @return whether the compression algorithm support */ @@ -385,7 +348,12 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, this->size += size; UT_LIST_ADD_LAST(chain, node); if (node->is_open()) { - ++fil_system.n_open; + n_pending.fetch_and(~CLOSING, std::memory_order_relaxed); + if (++fil_system.n_open >= srv_max_n_open_files) { + reacquire(); + try_to_close(true); + release(); + } } mutex_exit(&fil_system.mutex); @@ -422,7 +390,7 @@ static bool fil_node_open_file_low(fil_node_t *node) /* The following call prints an error message */ if (os_file_get_last_error(true) == EMFILE + 100 && - fil_try_to_close_file(true)) + fil_space_t::try_to_close(true)) continue; ib::warn() << "Cannot open '" << node->name << "'."; @@ -442,7 +410,7 @@ static bool fil_node_open_file_low(fil_node_t *node) if (UNIV_LIKELY(!fil_system.freeze_space_list)) { /* Move the file last in fil_system.space_list, so that - fil_try_to_close_file() should close it as a last resort. */ + fil_space_t::try_to_close() should close it as a last resort. */ UT_LIST_REMOVE(fil_system.space_list, node->space); UT_LIST_ADD_LAST(fil_system.space_list, node->space); } @@ -463,11 +431,11 @@ static bool fil_node_open_file(fil_node_t *node) srv_operation == SRV_OPERATION_RESTORE || srv_operation == SRV_OPERATION_RESTORE_DELTA); ut_ad(node->space->purpose != FIL_TYPE_TEMPORARY); - ut_ad(node->space->pending_io()); + ut_ad(node->space->referenced()); for (ulint count= 0; fil_system.n_open >= srv_max_n_open_files; count++) { - if (fil_try_to_close_file(count > 1)) + if (fil_space_t::try_to_close(count > 1)) count= 0; else if (count >= 2) { @@ -512,98 +480,59 @@ pfs_os_file_t fil_node_t::detach() void fil_node_t::prepare_to_close_or_detach() { ut_ad(mutex_own(&fil_system.mutex)); - ut_ad(space->is_closing()); - ut_ad(!space->pending_io()); + ut_ad(space->is_ready_to_close() || srv_operation == SRV_OPERATION_BACKUP || + srv_operation == SRV_OPERATION_RESTORE_DELTA); ut_a(is_open()); - ut_a(n_pending_flushes == 0); ut_a(!being_extended); - ut_a(!needs_flush || space->purpose == FIL_TYPE_TEMPORARY || + ut_a(space->is_ready_to_close() || space->purpose == FIL_TYPE_TEMPORARY || srv_fast_shutdown == 2 || !srv_was_started); ut_a(fil_system.n_open > 0); fil_system.n_open--; } -/** Flush any writes cached by the file system. -@param[in,out] space tablespace -@param[in] metadata whether to update file system metadata -@return whether fil_system.mutex was released and reacquired */ -static bool fil_flush_low(fil_space_t* space, bool metadata = false) +/** Flush any writes cached by the file system. */ +inline void fil_space_t::flush_low() { - ut_ad(mutex_own(&fil_system.mutex)); - ut_ad(!space->is_stopping()); - - if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { - /* No need to flush. User has explicitly disabled - buffering. */ - ut_ad(!space->is_in_unflushed_spaces); - ut_ad(fil_space_is_flushed(space)); - ut_ad(space->n_pending_flushes == 0); - -#ifdef UNIV_DEBUG - for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - node != NULL; - node = UT_LIST_GET_NEXT(chain, node)) { - ut_ad(!node->needs_flush); - ut_ad(node->n_pending_flushes == 0); - } -#endif /* UNIV_DEBUG */ - - if (!metadata) return false; - } - - bool reacquired = false; - /* Prevent dropping of the space while we are flushing */ - space->n_pending_flushes++; - - for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - node != NULL; - node = UT_LIST_GET_NEXT(chain, node)) { - - if (!node->needs_flush) { - continue; - } - - ut_a(node->is_open()); - - fil_n_pending_tablespace_flushes++; - -#ifdef _WIN32 - if (node->is_raw_disk) { - - goto skip_flush; - } -#endif /* _WIN32 */ - - ut_a(node->is_open()); - node->n_pending_flushes++; - node->needs_flush = false; - - mutex_exit(&fil_system.mutex); - - os_file_flush(node->handle); - reacquired = true; + ut_ad(!mutex_own(&fil_system.mutex)); - mutex_enter(&fil_system.mutex); + uint32_t n= 0; + while (!n_pending.compare_exchange_strong(n, (n + 1) | NEEDS_FSYNC, + std::memory_order_acquire, + std::memory_order_relaxed)) + { + if (n & STOPPING) + return; + if (!(n & NEEDS_FSYNC)) + continue; + if (acquire_low() & STOPPING) + return; + break; + } - node->n_pending_flushes--; -#ifdef _WIN32 -skip_flush: -#endif /* _WIN32 */ - if (!node->needs_flush) { - if (space->is_in_unflushed_spaces - && fil_space_is_flushed(space)) { - - fil_system.unflushed_spaces.remove(*space); - space->is_in_unflushed_spaces = false; - } - } + fil_n_pending_tablespace_flushes++; + for (fil_node_t *node= UT_LIST_GET_FIRST(chain); node; + node= UT_LIST_GET_NEXT(chain, node)) + { + ut_a(node->is_open()); + IF_WIN(if (node->is_raw_disk) continue,); + os_file_flush(node->handle); + } - fil_n_pending_tablespace_flushes--; - } + if (is_in_unflushed_spaces) + { + mutex_enter(&fil_system.mutex); + if (is_in_unflushed_spaces) + { + is_in_unflushed_spaces= false; + fil_system.unflushed_spaces.remove(*this); + } + mutex_exit(&fil_system.mutex); + } - space->n_pending_flushes--; - return reacquired; + clear_flush(); + release(); + fil_n_pending_tablespace_flushes--; } /** Try to extend a tablespace. @@ -624,7 +553,7 @@ fil_space_extend_must_retry( ut_ad(UT_LIST_GET_LAST(space->chain) == node); ut_ad(size >= FIL_IBD_FILE_INITIAL_SIZE); ut_ad(node->space == space); - ut_ad(space->pending_io()); + ut_ad(space->referenced() || space->is_being_truncated); *success = space->size >= size; @@ -698,28 +627,35 @@ fil_space_extend_must_retry( switch (space->id) { case TRX_SYS_SPACE: srv_sys_space.set_last_file_size(pages_in_MiB); - fil_flush_low(space, true); - return(false); + do_flush: + mutex_exit(&fil_system.mutex); + space->flush_low(); + mutex_enter(&fil_system.mutex); + break; default: ut_ad(space->purpose == FIL_TYPE_TABLESPACE || space->purpose == FIL_TYPE_IMPORT); if (space->purpose == FIL_TYPE_TABLESPACE && !space->is_being_truncated) { - fil_flush_low(space, true); + goto do_flush; } - return(false); + break; case SRV_TMP_SPACE_ID: ut_ad(space->purpose == FIL_TYPE_TEMPORARY); srv_tmp_space.set_last_file_size(pages_in_MiB); - return(false); + break; } + + return false; } /** @return whether the file is usable for io() */ -ATTRIBUTE_COLD bool fil_space_t::prepare_for_io() +ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex) { - ut_ad(pending_io()); - mutex_enter(&fil_system.mutex); + ut_ad(referenced()); + if (!have_mutex) + mutex_enter(&fil_system.mutex); + ut_ad(mutex_own(&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)); @@ -727,7 +663,7 @@ ATTRIBUTE_COLD bool fil_space_t::prepare_for_io() const bool is_open= node && (node->is_open() || fil_node_open_file(node)); if (!is_open) - release_for_io(); + release(); else if (auto desired_size= recv_size) { bool success; @@ -761,9 +697,10 @@ ATTRIBUTE_COLD bool fil_space_t::prepare_for_io() } else clear: - n_pending_ios.fetch_and(NOT_CLOSING); + n_pending.fetch_and(~CLOSING, std::memory_order_relaxed); - mutex_exit(&fil_system.mutex); + if (!have_mutex) + mutex_exit(&fil_system.mutex); return is_open; } @@ -774,28 +711,39 @@ clear: bool fil_space_extend(fil_space_t *space, uint32_t size) { ut_ad(!srv_read_only_mode || space->purpose == FIL_TYPE_TEMPORARY); - if (!space->acquire_for_io()) - return false; - - bool success; - - do - mutex_enter(&fil_system.mutex); - while (fil_space_extend_must_retry(space, UT_LIST_GET_LAST(space->chain), - size, &success)); - + bool success= false; + const bool acquired= space->acquire(); + mutex_enter(&fil_system.mutex); + if (acquired || space->is_being_truncated) + { + while (fil_space_extend_must_retry(space, UT_LIST_GET_LAST(space->chain), + size, &success)) + mutex_enter(&fil_system.mutex); + } mutex_exit(&fil_system.mutex); - space->release_for_io(); + if (acquired) + space->release(); return success; } /** Prepare to free a file from fil_system. */ -pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) +inline pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) { ut_ad(mutex_own(&fil_system.mutex)); ut_a(magic_n == FIL_NODE_MAGIC_N); ut_a(!being_extended); + if (is_open() && + (space->n_pending.fetch_or(fil_space_t::CLOSING, + std::memory_order_acquire) & + fil_space_t::PENDING)) + { + mutex_exit(&fil_system.mutex); + while (space->referenced()) + os_thread_sleep(100); + mutex_enter(&fil_system.mutex); + } + while (is_open()) { if (space->is_in_unflushed_spaces) @@ -805,14 +753,6 @@ pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) fil_system.unflushed_spaces.remove(*space); } - if (n_pending_flushes || space->set_closing()) - { - mutex_exit(&fil_system.mutex); - os_thread_sleep(100); - mutex_enter(&fil_system.mutex); - continue; - } - ut_a(!being_extended); if (detach_handle) { @@ -875,7 +815,7 @@ std::vector<pfs_os_file_t> fil_system_t::detach(fil_space_t *space, handles.push_back(handle); } - ut_ad(space->n_pending_flushes == 0); + ut_ad(!space->referenced()); return handles; } @@ -891,10 +831,10 @@ fil_space_free_low( ut_ad(srv_fast_shutdown == 2 || !srv_was_started || space->max_lsn == 0); - /* Wait for fil_space_t::release_for_io(); after + /* Wait for fil_space_t::release() after fil_system_t::detach(), the tablespace cannot be found, so - fil_space_t::get_for_io() would return NULL */ - while (space->pending_io()) { + fil_space_t::get() would return NULL */ + while (space->referenced()) { os_thread_sleep(100); } @@ -1001,7 +941,7 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags, space->magic_n = FIL_SPACE_MAGIC_N; space->crypt_data = crypt_data; - space->n_pending_ios.store(CLOSING, std::memory_order_relaxed); + space->n_pending.store(CLOSING, std::memory_order_relaxed); DBUG_LOG("tablespace", "Created metadata for " << id << " name " << name); @@ -1041,28 +981,10 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags, return(NULL); } - if ((purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT) - && id > fil_system.max_assigned_id) { - if (!fil_system.space_id_reuse_warned) { - fil_system.space_id_reuse_warned = true; - - ib::warn() << "Allocated tablespace ID " << id - << " for " << name << ", old maximum was " - << fil_system.max_assigned_id; - } - - fil_system.max_assigned_id = id; - } - HASH_INSERT(fil_space_t, hash, &fil_system.spaces, id, space); UT_LIST_ADD_LAST(fil_system.space_list, space); - if (id < SRV_SPACE_ID_UPPER_BOUND && id > fil_system.max_assigned_id) { - - fil_system.max_assigned_id = id; - } - switch (id) { case 0: ut_ad(!fil_system.sys_space); @@ -1072,6 +994,18 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags, 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 (!fil_system.space_id_reuse_warned) { + ib::warn() << "Allocated tablespace ID " << id + << " for " << name << ", old maximum was " + << fil_system.max_assigned_id; + } + + fil_system.max_assigned_id = id; } /* Inform key rotation that there could be something @@ -1157,9 +1091,13 @@ bool fil_space_t::read_page0() return false; ut_ad(!UT_LIST_GET_NEXT(chain, node)); - n_pending_ios.fetch_add(1, std::memory_order_acquire); + if (UNIV_UNLIKELY(acquire_low() & STOPPING)) + { + ut_ad("this should not happen" == 0); + return false; + } const bool ok= node->is_open() || fil_node_open_file(node); - release_for_io(); + release(); return ok; } @@ -1365,7 +1303,7 @@ void fil_system_t::close() } /** Close all tablespace files at shutdown */ -void fil_close_all_files() +void fil_space_t::close_all() { if (!fil_system.is_initialised()) { return; @@ -1395,8 +1333,7 @@ next: } for (ulint count = 10000; count--; ) { - if (!space->set_closing() - && !node->n_pending_flushes) { + if (!space->set_closing()) { node->close(); goto next; } @@ -1409,10 +1346,8 @@ next: } ib::error() << "File '" << node->name - << "' has " << space->pending_io() - << " operations and " - << node->n_pending_flushes - << " flushes"; + << "' has " << space->referenced() + << " operations"; } space = UT_LIST_GET_NEXT(space_list, space); @@ -1460,7 +1395,7 @@ fil_write_flushed_lsn( byte* buf; ut_ad(!srv_read_only_mode); - if (!fil_system.sys_space->acquire_for_io()) { + if (!fil_system.sys_space->acquire()) { return DB_ERROR; } @@ -1484,64 +1419,29 @@ fil_write_flushed_lsn( 0, srv_page_size, buf); fil_flush_file_spaces(); } else { - fil_system.sys_space->release_for_io(); + fil_system.sys_space->release(); } aligned_free(buf); return fio.err; } -/** Acquire a tablespace when it could be dropped concurrently. -Used by background threads that do not necessarily hold proper locks -for concurrency control. -@param[in] id tablespace ID -@param[in] silent whether to silently ignore missing tablespaces -@return the tablespace -@retval NULL if missing or being deleted */ -fil_space_t* fil_space_acquire_low(ulint id, bool silent) -{ - fil_space_t* space; - - mutex_enter(&fil_system.mutex); - - space = fil_space_get_by_id(id); - - if (space == NULL) { - if (!silent) { - ib::warn() << "Trying to access missing" - " tablespace " << id; - } - } else if (!space->acquire()) { - space = NULL; - } - - mutex_exit(&fil_system.mutex); - - return(space); -} - -/** Acquire a tablespace for reading or writing a block, -when it could be dropped concurrently. -@param[in] id tablespace ID -@return the tablespace -@retval NULL if missing */ -fil_space_t *fil_space_t::get_for_io(ulint id) +/** Acquire a tablespace reference. +@param id tablespace identifier +@return tablespace +@retval nullptr if the tablespace is missing or inaccessible */ +fil_space_t *fil_space_t::get(ulint id) { mutex_enter(&fil_system.mutex); - fil_space_t *space= fil_space_get_by_id(id); - - uint32_t f= space - ? space->n_pending_ios.fetch_add(1, std::memory_order_relaxed) - : 0; - + const uint32_t n= space ? space->acquire_low() : 0; mutex_exit(&fil_system.mutex); - if ((f & CLOSING) && !space->prepare_for_io()) - { - // FIXME: issue an error message! + if (n & STOPPING) + space= nullptr; + + if ((n & CLOSING) && !space->prepare()) space= nullptr; - } return space; } @@ -1777,7 +1677,6 @@ fil_check_pending_io( ulint count) /*!< in: number of attempts so far */ { ut_ad(mutex_own(&fil_system.mutex)); - ut_ad(!space->referenced()); /* The following code must change when InnoDB supports multiple datafiles per tablespace. */ @@ -1785,18 +1684,14 @@ fil_check_pending_io( *node = UT_LIST_GET_FIRST(space->chain); - const auto f = space->n_pending_flushes; - const auto p = space->pending_io(); - - if (f || p) { + if (const uint32_t p = space->referenced()) { ut_a(!(*node)->being_extended); /* Give a warning every 10 second, starting after 1 second */ if ((count % 500) == 50) { ib::info() << "Trying to delete" " tablespace '" << space->name - << "' but there are " << f - << " flushes and " << p + << "' but there are " << p << " pending i/o's on it."; } @@ -1824,13 +1719,14 @@ fil_check_pending_operations( fil_space_t* sp = fil_space_get_by_id(id); if (sp) { - if (sp->crypt_data && sp->acquire()) { + sp->set_stopping(true); + if (sp->crypt_data) { + sp->reacquire(); mutex_exit(&fil_system.mutex); fil_space_crypt_close_tablespace(sp); mutex_enter(&fil_system.mutex); sp->release(); } - sp->set_stopping(true); } /* Check for pending operations. */ @@ -1927,27 +1823,6 @@ void fil_close_tablespace(ulint id) ut_free(path); } -/** Determine whether a table can be accessed in operations that are -not (necessarily) protected by meta-data locks. -(Rollback would generally be protected, but rollback of -FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks -but only by InnoDB table locks, which may be broken by -lock_remove_all_on_table().) -@param[in] table persistent table -checked @return whether the table is accessible */ -bool fil_table_accessible(const dict_table_t* table) -{ - if (UNIV_UNLIKELY(!table->is_readable() || table->corrupted)) { - return(false); - } - - mutex_enter(&fil_system.mutex); - bool accessible = table->space && !table->space->is_stopping(); - mutex_exit(&fil_system.mutex); - ut_ad(accessible || dict_table_is_file_per_table(table)); - return accessible; -} - /** Delete a tablespace and associated .ibd file. @param[in] id tablespace identifier @param[in] if_exists whether to ignore missing tablespace @@ -2313,7 +2188,7 @@ fil_rename_tablespace( multiple datafiles per tablespace. */ ut_a(UT_LIST_GET_LEN(space->chain) == 1); node = UT_LIST_GET_FIRST(space->chain); - ut_a(space->acquire()); + space->reacquire(); mutex_exit(&fil_system.mutex); @@ -2423,10 +2298,7 @@ fil_ibd_create( file = os_file_create( innodb_data_file_key, path, OS_FILE_CREATE | OS_FILE_ON_ERROR_NO_EXIT, - OS_FILE_NORMAL, - OS_DATA_FILE, - srv_read_only_mode, - &success); + OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success); if (!success) { /* The following call will print an error message */ @@ -2452,7 +2324,7 @@ fil_ibd_create( const bool is_compressed = fil_space_t::is_compressed(flags); bool punch_hole = is_compressed; - + fil_space_crypt_t* crypt_data = nullptr; #ifdef _WIN32 if (is_compressed) { os_file_set_sparse_win32(file); @@ -2466,6 +2338,7 @@ fil_ibd_create( err_exit: os_file_close(file); os_file_delete(innodb_data_file_key, path); + free(crypt_data); return NULL; } @@ -2498,8 +2371,7 @@ err_exit: /* Create crypt data if the tablespace is either encrypted or user has requested it to remain unencrypted. */ - fil_space_crypt_t *crypt_data = (mode != FIL_ENCRYPTION_DEFAULT - || srv_encrypt_tables) + crypt_data = (mode != FIL_ENCRYPTION_DEFAULT || srv_encrypt_tables) ? fil_space_create_crypt_data(mode, key_id) : NULL; @@ -2557,17 +2429,11 @@ err_exit: } } - fil_space_t* space = fil_space_t::create(name, space_id, flags, - FIL_TYPE_TABLESPACE, - crypt_data, mode); - if (!space) { - free(crypt_data); - *err = DB_ERROR; - } else { + if (fil_space_t* space = fil_space_t::create(name, space_id, flags, + FIL_TYPE_TABLESPACE, + crypt_data, mode)) { space->punch_hole = punch_hole; - /* FIXME: Keep the file open! */ - fil_node_t* node = space->add(path, OS_FILE_CLOSED, size, - false, true); + fil_node_t* node = space->add(path, file, size, false, true); mtr_t mtr; mtr.start(); mtr.log_file_op(FILE_CREATE, space_id, node->name); @@ -2575,19 +2441,15 @@ err_exit: node->find_metadata(file); *err = DB_SUCCESS; + return space; } - os_file_close(file); - - if (*err != DB_SUCCESS) { - if (has_data_dir) { - RemoteDatafile::delete_link_file(name); - } - - os_file_delete(innodb_data_file_key, path); + if (has_data_dir) { + RemoteDatafile::delete_link_file(name); } - return space; + *err = DB_ERROR; + goto err_exit; } /** Try to open a single-table tablespace and optionally check that the @@ -2955,12 +2817,12 @@ skip_validate: df_remote.close(); df_dict.close(); df_default.close(); - if (space->acquire_for_io()) { + if (space->acquire()) { if (purpose != FIL_TYPE_IMPORT) { fsp_flags_try_adjust(space, flags & ~FSP_FLAGS_MEM_MASK); } - space->release_for_io(); + space->release(); } } @@ -3464,36 +3326,19 @@ fil_report_invalid_page_access(const char *name, inline void fil_node_t::complete_write() { ut_ad(!mutex_own(&fil_system.mutex)); - ut_ad(space->pending_io()); - if (space->purpose != FIL_TYPE_TEMPORARY && !space->is_stopping() && - srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC) + if (space->purpose != FIL_TYPE_TEMPORARY && + srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC && + space->set_needs_flush()) { mutex_enter(&fil_system.mutex); - if (!space->is_stopping()) + if (!space->is_in_unflushed_spaces) { - needs_flush= true; - - if (!space->is_in_unflushed_spaces) - { - space->is_in_unflushed_spaces= true; - fil_system.unflushed_spaces.push_front(*space); - } + space->is_in_unflushed_spaces= true; + fil_system.unflushed_spaces.push_front(*space); } mutex_exit(&fil_system.mutex); } -#ifdef UNIV_DEBUG - else - { - mutex_enter(&fil_system.mutex); - if (!space->is_stopping()) - { - ut_ad(!space->is_in_unflushed_spaces); - ut_ad(!needs_flush); - } - mutex_exit(&fil_system.mutex); - } -#endif /* UNIV_DEBUG */ } /** Read or write data. @@ -3506,7 +3351,7 @@ inline void fil_node_t::complete_write() fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len, void *buf, buf_page_t *bpage) { - ut_ad(pending_io()); + ut_ad(referenced()); ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad((len % OS_FILE_LOG_BLOCK_SIZE) == 0); ut_ad(fil_validate_skip()); @@ -3524,7 +3369,7 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len, if (type.type == IORequest::READ_ASYNC && is_stopping() && !is_being_truncated) { - release_for_io(); + release(); return {DB_TABLESPACE_DELETED, nullptr}; } @@ -3540,7 +3385,7 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len, node = UT_LIST_GET_NEXT(chain, node); if (!node) { if (type.type == IORequest::READ_ASYNC) { - release_for_io(); + release(); return {DB_ERROR, nullptr}; } fil_report_invalid_page_access(name, offset, @@ -3554,7 +3399,7 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len, if (UNIV_UNLIKELY(node->size <= p)) { if (type.type == IORequest::READ_ASYNC) { - release_for_io(); + release(); /* If we can tolerate the non-existent pages, we should return with DB_ERROR and let caller decide what to do. */ @@ -3594,7 +3439,7 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len, release_sync_write: node->complete_write(); release: - release_for_io(); + release(); } ut_ad(fil_validate_skip()); } @@ -3662,47 +3507,35 @@ write_completed: } } - node->space->release_for_io(); -} - -/** Flush pending writes from the file system cache to the file */ -void fil_space_t::flush() -{ - ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT); - if (!is_stopping()) - { - mutex_enter(&fil_system.mutex); - if (!is_stopping()) - fil_flush_low(this); - mutex_exit(&fil_system.mutex); - } + node->space->release(); } /** Flush to disk the writes in file spaces of the given type possibly cached by the OS. */ void fil_flush_file_spaces() { - if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { - ut_d(mutex_enter(&fil_system.mutex)); - ut_ad(fil_system.unflushed_spaces.empty()); - ut_d(mutex_exit(&fil_system.mutex)); - return; - } + if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) + { + ut_d(mutex_enter(&fil_system.mutex)); + ut_ad(fil_system.unflushed_spaces.empty()); + ut_d(mutex_exit(&fil_system.mutex)); + return; + } rescan: - mutex_enter(&fil_system.mutex); + mutex_enter(&fil_system.mutex); - for (sized_ilist<fil_space_t, unflushed_spaces_tag_t>::iterator it - = fil_system.unflushed_spaces.begin(), - end = fil_system.unflushed_spaces.end(); - it != end; ++it) { - if (!it->is_stopping() && fil_flush_low(&*it)) { - mutex_exit(&fil_system.mutex); - goto rescan; - } - } + for (fil_space_t &space : fil_system.unflushed_spaces) + { + if (space.needs_flush_not_stopping()) + { + mutex_exit(&fil_system.mutex); + space.flush_low(); + goto rescan; + } + } - mutex_exit(&fil_system.mutex); + mutex_exit(&fil_system.mutex); } /** Functor to validate the file node list of a tablespace. */ diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 7af8ee56893..ae8c557b24c 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1641,7 +1641,7 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr, { fseg_inode_t* inode; ib_id_t seg_id; - ulint n_reserved; + uint32_t n_reserved; DBUG_ENTER("fseg_create"); @@ -2196,7 +2196,7 @@ fseg_alloc_free_page_general( fil_space_t* space; buf_block_t* iblock; buf_block_t* block; - ulint n_reserved; + uint32_t n_reserved; space_id = page_get_space_id(page_align(seg_header)); space = mtr_x_lock_space(space_id, mtr); @@ -2308,64 +2308,64 @@ free pages available. @return true if we were able to make the reservation */ bool fsp_reserve_free_extents( - ulint* n_reserved, + uint32_t* n_reserved, fil_space_t* space, - ulint n_ext, + uint32_t n_ext, fsp_reserve_t alloc_type, mtr_t* mtr, uint32_t n_pages) { - ulint n_free_list_ext; - ulint free_limit; - ulint size; - ulint n_free; - ulint n_free_up; ulint reserve; size_t total_reserved = 0; ut_ad(mtr); *n_reserved = n_ext; + const uint32_t extent_size = FSP_EXTENT_SIZE; + mtr_x_lock_space(space, mtr); - const ulint physical_size = space->physical_size(); + const unsigned physical_size = space->physical_size(); buf_block_t* header = fsp_get_header(space, mtr); try_again: - size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame); + uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + + header->frame); ut_ad(size == space->size_in_header); - if (size < FSP_EXTENT_SIZE && n_pages < FSP_EXTENT_SIZE / 2) { + if (size < extent_size && n_pages < extent_size / 2) { /* Use different rules for small single-table tablespaces */ *n_reserved = 0; return(fsp_reserve_free_pages(space, header, size, mtr, n_pages)); } - n_free_list_ext = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE - + header->frame); + uint32_t n_free_list_ext = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE + + header->frame); ut_ad(space->free_len == n_free_list_ext); - free_limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT - + header->frame); + uint32_t free_limit = mach_read_from_4(FSP_HEADER_OFFSET + + FSP_FREE_LIMIT + + header->frame); ut_ad(space->free_limit == free_limit); /* Below we play safe when counting free extents above the free limit: some of them will contain extent descriptor pages, and therefore will not be free extents */ + uint32_t n_free_up; + if (size >= free_limit) { - n_free_up = (size - free_limit) / FSP_EXTENT_SIZE; + n_free_up = (size - free_limit) / extent_size; + if (n_free_up) { + n_free_up--; + n_free_up -= n_free_up / (physical_size / extent_size); + } } else { ut_ad(alloc_type == FSP_BLOB); n_free_up = 0; } - if (n_free_up > 0) { - n_free_up--; - n_free_up -= n_free_up / (physical_size / FSP_EXTENT_SIZE); - } - - n_free = n_free_list_ext + n_free_up; + uint32_t n_free = n_free_list_ext + n_free_up; switch (alloc_type) { case FSP_NORMAL: @@ -2373,7 +2373,7 @@ try_again: and 1 extent + 0.5 % to cleaning operations; NOTE: this source code is duplicated in the function below! */ - reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200; + reserve = 2 + ((size / extent_size) * 2) / 200; if (n_free <= reserve + n_ext) { @@ -2383,7 +2383,7 @@ try_again: case FSP_UNDO: /* We reserve 0.5 % of the space size to cleaning operations */ - reserve = 1 + ((size / FSP_EXTENT_SIZE) * 1) / 200; + reserve = 1 + ((size / extent_size) * 1) / 200; if (n_free <= reserve + n_ext) { @@ -2435,10 +2435,12 @@ fseg_free_page_low( ut_ad(iblock->frame == page_align(seg_inode)); ut_d(space->modify_check(*mtr)); + const uint32_t extent_size = FSP_EXTENT_SIZE; + ut_ad(ut_is_2pow(extent_size)); buf_block_t* xdes; xdes_t* descr = xdes_get_descriptor(space, offset, &xdes, mtr); - if (xdes_is_free(descr, offset % FSP_EXTENT_SIZE)) { + if (xdes_is_free(descr, offset & (extent_size - 1))) { ib::fatal() << "InnoDB is trying to free page " << page_id_t(space->id, offset) << " though it is already marked as free in the" @@ -2499,7 +2501,7 @@ fseg_free_page_low( flst_add_last(iblock, static_cast<uint16_t>(FSEG_NOT_FULL + ioffset), xdes, xoffset, mtr); - not_full_n_used += FSP_EXTENT_SIZE - 1; + not_full_n_used += extent_size - 1; } else { ut_a(not_full_n_used > 0); not_full_n_used--; @@ -2507,7 +2509,7 @@ fseg_free_page_low( mtr->write<4>(*iblock, p_not_full, not_full_n_used); - const ulint bit = offset % FSP_EXTENT_SIZE; + const ulint bit = offset & (extent_size - 1); xdes_set_free<true>(*xdes, descr, bit, mtr); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 20ba44a8d73..b0324bf7667 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -2389,7 +2389,7 @@ fts_optimize_table_bk( dict_table_t* table = slot->table; dberr_t error; - if (fil_table_accessible(table) + if (table->is_accessible() && table->fts && table->fts->cache && table->fts->cache->deleted >= FTS_OPTIMIZE_THRESHOLD) { error = fts_optimize_table(table); @@ -2799,8 +2799,7 @@ static void fts_optimize_sync_table(dict_table_t *table, if (!sync_table) return; - if (sync_table->fts && sync_table->fts->cache && - fil_table_accessible(sync_table)) + if (sync_table->fts && sync_table->fts->cache && sync_table->is_accessible()) { fts_sync_table(sync_table, false); if (process_message) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 97cce77135b..b636592bb87 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -17481,7 +17481,7 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save) mtr_t mtr; uint space_id = *static_cast<const uint*>(save); mysql_mutex_unlock(&LOCK_global_system_variables); - fil_space_t* space = fil_space_acquire_silent(space_id); + fil_space_t* space = fil_space_t::get(space_id); if (space == NULL) { func_exit_no_space: diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index e7e66bb0e8d..b0dc115977e 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -6551,7 +6551,7 @@ i_s_dict_fill_sys_tablespaces( memset(&file, 0xff, sizeof(file)); memset(&stat, 0x0, sizeof(stat)); - if (fil_space_t* s = fil_space_acquire_silent(space)) { + if (fil_space_t* s = fil_space_t::get(space)) { const char *filepath = s->chain.start ? s->chain.start->name : NULL; if (!filepath) { @@ -7049,7 +7049,8 @@ i_s_tablespaces_encryption_fill_table( for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); space; space = UT_LIST_GET_NEXT(space_list, space)) { if (space->purpose == FIL_TYPE_TABLESPACE - && space->acquire()) { + && !space->is_stopping()) { + space->reacquire(); mutex_exit(&fil_system.mutex); if (int err = i_s_dict_fill_tablespaces_encryption( thd, space, tables->table)) { diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 9e9bc241828..5c9d7955c90 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -2300,7 +2300,7 @@ static void ibuf_read_merge_pages(const uint32_t* space_ids, for (ulint i = 0; i < n_stored; i++) { const ulint space_id = space_ids[i]; - fil_space_t* s = fil_space_t::get_for_io(space_id); + fil_space_t* s = fil_space_t::get(space_id); if (!s) { tablespace_deleted: /* The tablespace was not found: remove all @@ -2314,7 +2314,7 @@ tablespace_deleted: } const ulint zip_size = s->zip_size(), size = s->size; - s->release_for_io(); + s->release(); mtr_t mtr; if (UNIV_LIKELY(page_nos[i] < size)) { @@ -4028,7 +4028,7 @@ ibuf_restore_pos( return true; } - if (fil_space_t* s = fil_space_acquire_silent(page_id.space())) { + if (fil_space_t* s = fil_space_t::get(page_id.space())) { ib::error() << "ibuf cursor restoration fails!" " ibuf record inserted to page " << page_id @@ -4214,7 +4214,7 @@ ibuf_merge_or_delete_for_page( fil_space_t* space; if (update_ibuf_bitmap) { - space = fil_space_acquire_silent(page_id.space()); + space = fil_space_t::get(page_id.space()); if (UNIV_UNLIKELY(!space)) { /* Do not try to read the bitmap page from the diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 1ae52dfbf5d..68eb417e531 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1806,6 +1806,13 @@ struct dict_table_t { return(UNIV_LIKELY(!file_unreadable)); } + /** @return whether the table is accessible */ + bool is_accessible() const + { + return UNIV_LIKELY(is_readable() && !corrupted && space) + && !space->is_stopping(); + } + /** Check if a table name contains the string "/#sql" which denotes temporary or intermediate tables in MariaDB. */ static bool is_temporary_name(const char* name) diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 57e5c43199b..a980c21ead0 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -317,7 +317,7 @@ struct fil_io_t { /** error code */ dberr_t err; - /** file; node->space->release_for_io() must follow IORequestRead call */ + /** file; node->space->release() must follow IORequestRead call */ fil_node_t *node; }; @@ -332,13 +332,14 @@ enum fil_encryption_t FIL_ENCRYPTION_OFF }; -struct fil_space_t : ilist_node<unflushed_spaces_tag_t>, - ilist_node<rotation_list_tag_t> +struct fil_space_t final : + ilist_node<unflushed_spaces_tag_t>, ilist_node<rotation_list_tag_t> #else -struct fil_space_t +struct fil_space_t final #endif { #ifndef UNIV_INNOCHECKSUM + friend fil_node_t; ulint id; /*!< space id */ hash_node_t hash; /*!< hash chain node */ char* name; /*!< Tablespace name */ @@ -367,39 +368,27 @@ 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 n_reserved_extents; + uint32_t n_reserved_extents; /*!< number of reserved free extents for ongoing operations like B-tree page split */ - ulint n_pending_flushes; /*!< this is positive when flushing - the tablespace to disk; dropping of the - tablespace is forbidden if this is positive */ private: /** the committed size of the tablespace in pages */ Atomic_relaxed<uint32_t> committed_size; - /** Number of pending buffer pool operations accessing the - tablespace without holding a table lock or dict_operation_lock - S-latch that would prevent the table (and tablespace) from being - dropped. An example is encryption key rotation. - - The tablespace cannot be dropped while this is nonzero. - - The most significant bit contains the STOP_NEW_OPS flag. */ - Atomic_relaxed<uint32_t> n_pending_ops; - /** Number of pending block read or write operations - The tablespace object cannot be freed while this is nonzero, - but it can be detached from fil_system. - - The most significant bit contains the CLOSING flag. */ - std::atomic<uint32_t> n_pending_ios; - - /** Flag in n_pending_ops that indicates that the tablespace is being + /** Number of pending operations on the file. + The tablespace cannot be freed while (n_pending & PENDING) != 0. */ + std::atomic<uint32_t> n_pending; + /** Flag in n_pending that indicates that the tablespace is being deleted, and no further operations should be performed */ - static constexpr uint32_t STOP_NEW_OPS= ~(~uint32_t(0) >> 1); - /** Flag in n_pending_ios that indicates that the tablespace is a candidate + static constexpr uint32_t STOPPING= 1U << 31; + /** Flag in n_pending that indicates that the tablespace is a candidate for being closed, and fil_node_t::is_open() can only be trusted after acquiring fil_system.mutex and resetting the flag */ - static constexpr uint32_t CLOSING= STOP_NEW_OPS; - static constexpr uint32_t NOT_CLOSING= ~CLOSING; + static constexpr uint32_t CLOSING= 1U << 30; + /** Flag in n_pending that indicates that the tablespace needs fsync(). + This must be the least significant flag bit; @see release_flush() */ + static constexpr uint32_t NEEDS_FSYNC= 1U << 29; + /** The reference count */ + static constexpr uint32_t PENDING= ~(STOPPING | CLOSING | NEEDS_FSYNC); public: rw_lock_t latch; /*!< latch protecting the file space storage allocation */ @@ -467,7 +456,7 @@ public: @param[in] n_free_now current number of free extents @param[in] n_to_reserve number of extents to reserve @return whether the reservation succeeded */ - bool reserve_free_extents(ulint n_free_now, ulint n_to_reserve) + bool reserve_free_extents(uint32_t n_free_now, uint32_t n_to_reserve) { ut_ad(rw_lock_own(&latch, RW_LOCK_X)); if (n_reserved_extents + n_to_reserve > n_free_now) { @@ -480,7 +469,7 @@ public: /** Release the reserved free extents. @param[in] n_reserved number of reserved extents */ - void release_free_extents(ulint n_reserved) + void release_free_extents(uint32_t n_reserved) { if (!n_reserved) return; ut_ad(rw_lock_own(&latch, RW_LOCK_X)); @@ -513,70 +502,91 @@ public: /** Close each file. Only invoked on fil_system.temp_space. */ void close(); - /** @return whether the tablespace is about to be dropped */ - bool is_stopping() const { return n_pending_ops & STOP_NEW_OPS; } - - /** @return number of references being held */ - size_t referenced() const { return n_pending_ops & ~STOP_NEW_OPS; } - /** Note that operations on the tablespace must stop or can resume */ inline void set_stopping(bool stopping); +private: MY_ATTRIBUTE((warn_unused_result)) - /** @return whether a tablespace reference was successfully acquired */ - bool acquire() + /** Try to acquire a tablespace reference. + @return the old reference count (if STOPPING is set, it was not acquired) */ + uint32_t acquire_low() { uint32_t n= 0; - while (!n_pending_ops.compare_exchange_strong(n, n + 1, - std::memory_order_acquire, - std::memory_order_relaxed)) - if (UNIV_UNLIKELY(n & STOP_NEW_OPS)) - return false; - return true; - } - /** Release a tablespace reference. - @return whether this was the last reference */ - bool release() - { - auto n= n_pending_ops.fetch_sub(1); - ut_ad(n & ~STOP_NEW_OPS); - return (n & ~STOP_NEW_OPS) == 1; + while (!n_pending.compare_exchange_strong(n, n + 1, + std::memory_order_acquire, + std::memory_order_relaxed) && + !(n & STOPPING)); + return n; } +public: + MY_ATTRIBUTE((warn_unused_result)) + /** @return whether a tablespace reference was successfully acquired */ + inline bool acquire_if_not_stopped(bool have_mutex= false); MY_ATTRIBUTE((warn_unused_result)) /** Acquire a tablespace reference for I/O. @return whether the file is usable */ - bool acquire_for_io() + bool acquire() { - return UNIV_LIKELY(!(n_pending_ios.fetch_add(1, std::memory_order_acquire)& - CLOSING)) || - prepare_for_io(); + uint32_t n= acquire_low(); + if (UNIV_LIKELY(!(n & (STOPPING | CLOSING)))) + return true; + return UNIV_LIKELY(!(n & STOPPING)) && prepare(); } /** Acquire another tablespace reference for I/O. */ - inline void reacquire_for_io(); + inline void reacquire(); - /** Release a tablespace reference for I/O. */ - void release_for_io() + /** Release a tablespace reference. + @return whether this was the last reference */ + bool release() { - ut_d(uint32_t n=) n_pending_ios.fetch_sub(1, std::memory_order_release); - ut_ad(n & NOT_CLOSING); + uint32_t n= n_pending.fetch_sub(1, std::memory_order_release); + ut_ad(n & PENDING); + return (n & PENDING) == 1; } - /** @return number of pending reads or writes */ - uint32_t pending_io() const - { return n_pending_ios.load(std::memory_order_acquire) & NOT_CLOSING; } + /** Clear the NEEDS_FSYNC flag */ + void clear_flush() + { n_pending.fetch_and(~NEEDS_FSYNC, std::memory_order_release); } + +private: + /** @return pending operations (and flags) */ + uint32_t pending()const { return n_pending.load(std::memory_order_acquire); } +public: + /** @return whether close() of the file handle has been requested */ + bool is_closing() const { return pending() & CLOSING; } + /** @return whether the tablespace is going to be dropped */ + bool is_stopping() const { return pending() & STOPPING; } + /** @return number of pending operations */ + bool is_ready_to_close() const + { return (pending() & (PENDING | CLOSING)) == CLOSING; } + /** @return whether fsync() or similar is needed */ + bool needs_flush() const { return pending() & NEEDS_FSYNC; } + /** @return whether fsync() or similar is needed, and the tablespace is + not being dropped */ + bool needs_flush_not_stopping() const + { return (pending() & (NEEDS_FSYNC | STOPPING)) == NEEDS_FSYNC; } + + uint32_t referenced() const { return pending() & PENDING; } +private: MY_ATTRIBUTE((warn_unused_result)) /** Prepare to close the file handle. - @return number of pending operations */ + @return number of pending operations, possibly with NEEDS_FSYNC flag */ uint32_t set_closing() { - return n_pending_ios.fetch_or(CLOSING, std::memory_order_acquire) & - NOT_CLOSING; + return n_pending.fetch_or(CLOSING, std::memory_order_acquire) & + (PENDING | NEEDS_FSYNC); } - /** @return whether close() of the file handle has been requested */ - bool is_closing() const - { return n_pending_ios.load(std::memory_order_acquire) & CLOSING; } + +public: + /** Try to close a file to adhere to the innodb_open_files limit. + @param print_info whether to diagnose why a file cannot be closed + @return whether a file was closed */ + static bool try_to_close(bool print_info); + + /** Close all tablespace files at shutdown */ + static void close_all(); /** @return last_freed_lsn */ lsn_t get_last_freed_lsn() { return last_freed_lsn; } @@ -587,6 +597,23 @@ public: last_freed_lsn= lsn; } + /** Note that the file will need fsync(). + @return whether this needs to be added to fil_system.unflushed_spaces */ + bool set_needs_flush() + { + uint32_t n= 1; + while (!n_pending.compare_exchange_strong(n, n | NEEDS_FSYNC, + std::memory_order_acquire, + std::memory_order_relaxed)) + { + ut_ad(n & PENDING); + if (n & (NEEDS_FSYNC | STOPPING)) + return false; + } + + return true; + } + /** Clear all freed ranges for undo tablespace when InnoDB encounters TRIM redo log record */ void clear_freed_ranges() @@ -879,17 +906,19 @@ public: fil_type_t purpose, fil_space_crypt_t *crypt_data, fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT); - /** Acquire a tablespace for reading or writing a block. - @param id tablespace ID - @return the tablespace, or nullptr if missing or inaccessible */ - static fil_space_t *get_for_io(ulint id); + MY_ATTRIBUTE((warn_unused_result)) + /** Acquire a tablespace reference. + @param id tablespace identifier + @return tablespace + @retval nullptr if the tablespace is missing or inaccessible */ + static fil_space_t *get(ulint id); /** Add/remove the free page in the freed ranges list. @param[in] offset page number to be added @param[in] free true if page to be freed */ void free_page(uint32_t offset, bool add=true) { - std::lock_guard<std::mutex> freed_lock(freed_range_mutex); + std::lock_guard<std::mutex> freed_lock(freed_range_mutex); if (add) return freed_ranges.add_value(offset); @@ -902,7 +931,7 @@ public: /** Add the range of freed pages */ void add_free_ranges(range_set ranges) { - std::lock_guard<std::mutex> freed_lock(freed_range_mutex); + std::lock_guard<std::mutex> freed_lock(freed_range_mutex); freed_ranges= std::move(ranges); } @@ -942,16 +971,28 @@ public: @return status and file descriptor */ fil_io_t io(const IORequest &type, os_offset_t offset, size_t len, void *buf, buf_page_t *bpage= nullptr); - /** Flush pending writes from the file system cache to the file */ - void flush(); + /** Flush pending writes from the file system cache to the file. */ + inline void flush(); + /** Flush pending writes from the file system cache to the file. */ + void flush_low(); /** Read the first page of a data file. @return whether the page was found valid */ bool read_page0(); + /** Determine the next tablespace for encryption key rotation. + @param space current tablespace (nullptr to start from the beginning) + @param recheck whether the removal condition needs to be rechecked after + encryption parameters were changed + @param encrypt expected state of innodb_encrypt_tables + @return the next tablespace + @retval nullptr upon reaching the end of the iteration */ + static inline fil_space_t *next(fil_space_t *space, bool recheck, + bool encrypt); + private: /** @return whether the file is usable for io() */ - ATTRIBUTE_COLD bool prepare_for_io(); + ATTRIBUTE_COLD bool prepare(bool have_mutex= false); #endif /*!UNIV_INNOCHECKSUM */ }; @@ -960,7 +1001,8 @@ private: #define FIL_SPACE_MAGIC_N 89472 /** File node of a tablespace or the log data space */ -struct fil_node_t { +struct fil_node_t final +{ /** tablespace containing this file */ fil_space_t* space; /** file name; protected by fil_system.mutex and log_sys.mutex. */ @@ -980,12 +1022,8 @@ struct fil_node_t { uint32_t init_size; /** maximum size of the file in database pages (0 if unlimited) */ uint32_t max_size; - /** count of pending flushes; is_open must be true if nonzero */ - ulint n_pending_flushes; /** whether the file is currently being extended */ Atomic_relaxed<bool> being_extended; - /** whether this file had writes after lasy fsync() */ - bool needs_flush; /** link to other files in this tablespace */ UT_LIST_NODE_T(fil_node_t) chain; @@ -1023,7 +1061,7 @@ struct fil_node_t { /** Prepare to free a file from fil_system. @param detach_handle whether to detach instead of closing a handle @return detached handle or OS_FILE_CLOSED */ - pfs_os_file_t close_to_free(bool detach_handle= false); + inline pfs_os_file_t close_to_free(bool detach_handle= false); /** Update the data structures on write completion */ inline void complete_write(); @@ -1036,13 +1074,6 @@ private: /** Value of fil_node_t::magic_n */ #define FIL_NODE_MAGIC_N 89389 -inline void fil_space_t::reacquire_for_io() -{ - ut_d(uint32_t n=) n_pending_ios.fetch_add(1, std::memory_order_relaxed); - ut_ad(n & NOT_CLOSING); - ut_ad(UT_LIST_GET_FIRST(chain)->is_open()); -} - inline void fil_space_t::set_imported() { ut_ad(purpose == FIL_TYPE_IMPORT); @@ -1278,15 +1309,14 @@ inline uint16_t fil_page_get_type(const byte *page) #ifndef UNIV_INNOCHECKSUM /** Number of pending tablespace flushes */ -extern ulint fil_n_pending_tablespace_flushes; +extern Atomic_counter<ulint> fil_n_pending_tablespace_flushes; /** Look up a tablespace. The caller should hold an InnoDB table lock or a MDL that prevents the tablespace from being dropped during the operation, or the caller should be in single-threaded crash recovery mode (no user connections that could drop tablespaces). -If this is not the case, fil_space_acquire() and fil_space_t::release() -should be used instead. +Normally, fil_space_t::get() should be used instead. @param[in] id tablespace ID @return tablespace, or NULL if not found */ fil_space_t* @@ -1352,12 +1382,8 @@ public: fil_space_t* temp_space; /*!< The innodb_temporary tablespace */ /** Map of fil_space_t::id to fil_space_t* */ hash_table_t spaces; - sized_ilist<fil_space_t, unflushed_spaces_tag_t> unflushed_spaces; - /*!< list of those - tablespaces whose files contain - unflushed writes; those spaces have - at least one file node where - needs_flush == true */ + /** tablespaces for which fil_space_t::needs_flush() holds */ + sized_ilist<fil_space_t, unflushed_spaces_tag_t> unflushed_spaces; /** number of currently open files; protected by mutex */ ulint n_open; ulint max_assigned_id;/*!< maximum space id in the existing @@ -1400,12 +1426,44 @@ public: /** The tablespace memory cache. */ extern fil_system_t fil_system; +inline void fil_space_t::reacquire() +{ + ut_d(uint32_t n=) n_pending.fetch_add(1, std::memory_order_relaxed); + ut_d(if (mutex_own(&fil_system.mutex)) return); + ut_ad(n & PENDING); + ut_ad(UT_LIST_GET_FIRST(chain)->is_open()); +} + +inline bool fil_space_t::acquire_if_not_stopped(bool have_mutex) +{ + ut_ad(mutex_own(&fil_system.mutex) == have_mutex); + const uint32_t n= acquire_low(); + if (UNIV_LIKELY(!(n & (STOPPING | CLOSING)))) + return true; + return UNIV_LIKELY(!(n & CLOSING)) || prepare(have_mutex); +} + /** Note that operations on the tablespace must stop or can resume */ inline void fil_space_t::set_stopping(bool stopping) { ut_ad(mutex_own(&fil_system.mutex)); - ut_d(auto n=) n_pending_ops.fetch_xor(STOP_NEW_OPS); - ut_ad(!(n & STOP_NEW_OPS) == stopping); + ut_d(auto n=) n_pending.fetch_xor(STOPPING, std::memory_order_relaxed); + ut_ad(!(n & STOPPING) == stopping); +} + +/** Flush pending writes from the file system cache to the file. */ +inline void fil_space_t::flush() +{ + ut_ad(!mutex_own(&fil_system.mutex)); + + ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT); + if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) + { + ut_ad(!is_in_unflushed_spaces); + ut_ad(!needs_flush()); + } + else + flush_low(); } /** @return the size in pages (0 if unreadable) */ @@ -1450,8 +1508,6 @@ fil_space_free( void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, uint32_t flags); -/** Close all tablespace files at shutdown */ -void fil_close_all_files(); /*******************************************************************//** Sets the max tablespace id counter if the given number is bigger than the previous value. */ @@ -1469,42 +1525,6 @@ fil_write_flushed_lsn( lsn_t lsn) MY_ATTRIBUTE((warn_unused_result)); -/** Acquire a tablespace when it could be dropped concurrently. -Used by background threads that do not necessarily hold proper locks -for concurrency control. -@param[in] id tablespace ID -@param[in] silent whether to silently ignore missing tablespaces -@return the tablespace -@retval NULL if missing or being deleted */ -fil_space_t* fil_space_acquire_low(ulint id, bool silent) - MY_ATTRIBUTE((warn_unused_result)); - -/** Acquire a tablespace when it could be dropped concurrently. -Used by background threads that do not necessarily hold proper locks -for concurrency control. -@param[in] id tablespace ID -@return the tablespace -@retval NULL if missing or being deleted or truncated */ -inline -fil_space_t* -fil_space_acquire(ulint id) -{ - return (fil_space_acquire_low(id, false)); -} - -/** Acquire a tablespace that may not exist. -Used by background threads that do not necessarily hold proper locks -for concurrency control. -@param[in] id tablespace ID -@return the tablespace -@retval NULL if missing or being deleted */ -inline -fil_space_t* -fil_space_acquire_silent(ulint id) -{ - return (fil_space_acquire_low(id, true)); -} - /** Replay a file rename operation if possible. @param[in] space_id tablespace identifier @param[in] name old file name @@ -1519,17 +1539,6 @@ fil_op_replay_rename( const char* new_name) MY_ATTRIBUTE((warn_unused_result)); -/** Determine whether a table can be accessed in operations that are -not (necessarily) protected by meta-data locks. -(Rollback would generally be protected, but rollback of -FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks -but only by InnoDB table locks, which may be broken by -lock_remove_all_on_table().) -@param[in] table persistent table -checked @return whether the table is accessible */ -bool fil_table_accessible(const dict_table_t* table) - MY_ATTRIBUTE((warn_unused_result, nonnull)); - /** Delete a tablespace and associated .ibd file. @param[in] id tablespace identifier @param[in] if_exists whether to ignore missing tablespace diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 7a0687d4960..7db85e87ed0 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -268,6 +268,14 @@ public: return(m_handle); } + /** @return detached file handle */ + pfs_os_file_t detach() + { + pfs_os_file_t detached = m_handle; + m_handle = OS_FILE_CLOSED; + return detached; + } + /** Get Datafile::m_order. @return m_order */ ulint order() const diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 308b0916284..7245db39273 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -466,9 +466,9 @@ free pages available. @return true if we were able to make the reservation */ bool fsp_reserve_free_extents( - ulint* n_reserved, + uint32_t* n_reserved, fil_space_t* space, - ulint n_ext, + uint32_t n_ext, fsp_reserve_t alloc_type, mtr_t* mtr, uint32_t n_pages = 2); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 71077e3f9fb..42ab5d061af 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4949,7 +4949,7 @@ static void lock_rec_block_validate(const page_id_t page_id) discard or rebuild a tablespace do hold an exclusive table lock, which would conflict with any locks referring to the tablespace from other transactions. */ - if (fil_space_t* space = fil_space_acquire(page_id.space())) { + if (fil_space_t* space = fil_space_t::get(page_id.space())) { dberr_t err = DB_SUCCESS; mtr_start(&mtr); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 1fe5c70bcf7..8eeadc8e805 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2060,14 +2060,14 @@ same_page: const bool is_init= (b & 0x70) <= INIT_PAGE; switch (*store) { case STORE_IF_EXISTS: - if (fil_space_t *space= fil_space_acquire_silent(space_id)) + if (fil_space_t *space= fil_space_t::get(space_id)) { const auto size= space->get_size(); - space->release(); - if (!size) + space->release(); + if (!size) continue; - } - else + } + else continue; /* fall through */ case STORE_YES: @@ -2312,7 +2312,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, if (fil_space_t* s = space ? space - : fil_space_acquire(block->page.id().space())) { + : fil_space_t::get(block->page.id().space())) { switch (a) { case log_phys_t::APPLIED_TO_FSP_HEADER: s->flags = mach_read_from_4( @@ -2351,7 +2351,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, fil_crypt_parse(s, b); } - if (s != space) { + if (!space) { s->release(); } } @@ -2520,7 +2520,7 @@ inline buf_block_t *recv_sys_t::recover_low(const page_id_t page_id, if (end_lsn < i.lsn) DBUG_LOG("ib_log", "skip log for page " << page_id << " LSN " << end_lsn << " < " << i.lsn); - else if (fil_space_t *space= fil_space_t::get_for_io(page_id.space())) + else if (fil_space_t *space= fil_space_t::get(page_id.space())) { mtr.start(); mtr.set_log_mode(MTR_LOG_NO_REDO); @@ -2547,7 +2547,7 @@ inline buf_block_t *recv_sys_t::recover_low(const page_id_t page_id, map::iterator r= p++; recv_sys.pages.erase(r); } - space->release_for_io(); + space->release(); } return block; diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index cdf61f12ce4..0b9438d2a08 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4170,7 +4170,7 @@ os_aio_print(FILE* file) ULINTPF " OS file writes, " ULINTPF " OS fsyncs\n", log_sys.get_pending_flushes(), - fil_n_pending_tablespace_flushes, + ulint{fil_n_pending_tablespace_flushes}, os_n_file_reads, os_n_file_writes, os_n_fsyncs); diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 987c5b60f21..1529d8050db 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -401,7 +401,7 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) goto close_table; } - if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) { + if (UNIV_UNLIKELY(!node->table->is_accessible())) { close_table: /* Normally, tables should not disappear or become unaccessible during ROLLBACK, because they should be diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index af35dc1af7f..f710f54d0c1 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1235,7 +1235,7 @@ static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked) ut_ad(!node->table->skip_alter_undo); - if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) { + if (UNIV_UNLIKELY(!node->table->is_accessible())) { close_table: /* Normally, tables should not disappear or become unaccessible during ROLLBACK, because they should be diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 44d33126e48..030acc72e63 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -697,7 +697,6 @@ static bool need_srv_free; static void srv_init() { mutex_create(LATCH_ID_SRV_INNODB_MONITOR, &srv_innodb_monitor_mutex); - srv_thread_pool_init(); if (!srv_read_only_mode) { mutex_create(LATCH_ID_SRV_SYS_TASKS, &srv_sys.tasks_mutex); @@ -761,6 +760,7 @@ void srv_boot(void) /*==========*/ { + srv_thread_pool_init(); sync_check_init(); trx_pool_init(); row_mysql_init(); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index d4ee4dc3c4b..78b7cbb635b 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2028,7 +2028,7 @@ void innodb_shutdown() } os_aio_free(); - fil_close_all_files(); + fil_space_t::close_all(); /* Exit any remaining threads. */ ut_ad(!buf_page_cleaner_is_active); srv_shutdown_threads(); diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index e6ec441bdeb..1f3ce121c28 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -359,7 +359,7 @@ trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id, dberr_t *err, mtr_t *mtr) { buf_block_t* block; - ulint n_reserved; + uint32_t n_reserved; bool success; const ulint slot_no = trx_rsegf_undo_find_free(rseg_hdr); @@ -551,7 +551,7 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr) { trx_rseg_t* rseg = undo->rseg; buf_block_t* new_block = NULL; - ulint n_reserved; + uint32_t n_reserved; /* When we add a page to an undo log, this is analogous to a pessimistic insert in a B-tree, and we must reserve the |