diff options
author | Sergei Golubchik <serg@mariadb.org> | 2017-08-25 10:25:48 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-08-25 10:25:48 +0200 |
commit | 27412877dbcf601676f4515a99b2abee1f19623b (patch) | |
tree | 2cb1a2e1a58ba10f2a96fcdec43f5ed77c326fd0 /storage/innobase/fil | |
parent | f2033df6ac0f64664d9aad2d56fdd74f4bf9d666 (diff) | |
parent | a544225d0a772bd4b67c96f5861ecc0ef7e69bba (diff) | |
download | mariadb-git-27412877dbcf601676f4515a99b2abee1f19623b.tar.gz |
Merge branch '10.2' into bb-10.2-ext
Diffstat (limited to 'storage/innobase/fil')
-rw-r--r-- | storage/innobase/fil/fil0crypt.cc | 123 |
1 files changed, 69 insertions, 54 deletions
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 6e431a6ee0f..e1b5bcbc325 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -93,13 +93,20 @@ static ib_mutex_t crypt_stat_mutex; extern my_bool srv_background_scrub_data_uncompressed; extern my_bool srv_background_scrub_data_compressed; +/*********************************************************************** +Check if a key needs rotation given a key_state +@param[in] encrypt_mode Encryption mode +@param[in] key_version Current key version +@param[in] latest_key_version Latest key version +@param[in] rotate_key_age when to rotate +@return true if key needs rotation, false if not */ static bool fil_crypt_needs_rotation( - fil_encryption_t encrypt_mode, /*!< in: Encryption - mode */ - uint key_version, /*!< in: Key version */ - uint latest_key_version, /*!< in: Latest key version */ - uint rotate_key_age); /*!< in: When to rotate */ + fil_encryption_t encrypt_mode, + uint key_version, + uint latest_key_version, + uint rotate_key_age) + MY_ATTRIBUTE((warn_unused_result)); /********************************************************************* Init space crypt */ @@ -326,10 +333,17 @@ fil_space_destroy_crypt_data( fil_space_crypt_t **crypt_data) { if (crypt_data != NULL && (*crypt_data) != NULL) { - mutex_enter(&fil_crypt_threads_mutex); - fil_space_crypt_t* c = *crypt_data; - *crypt_data = NULL; - mutex_exit(&fil_crypt_threads_mutex); + fil_space_crypt_t* c; + if (UNIV_LIKELY(fil_crypt_threads_inited)) { + mutex_enter(&fil_crypt_threads_mutex); + c = *crypt_data; + *crypt_data = NULL; + mutex_exit(&fil_crypt_threads_mutex); + } else { + ut_ad(srv_read_only_mode || !srv_was_started); + c = *crypt_data; + *crypt_data = NULL; + } if (c) { c->~fil_space_crypt_t(); ut_free(c); @@ -1582,20 +1596,6 @@ fil_crypt_find_page_to_rotate( return found; } -/*********************************************************************** -Check if a page is uninitialized (doesn't need to be rotated) -@param[in] frame Page to check -@param[in] page_size Page size -@return true if page is uninitialized, false if not. */ -static inline -bool -fil_crypt_is_page_uninitialized( - const byte *frame, - const page_size_t& page_size) -{ - return (buf_page_is_zeroes(frame, page_size)); -} - #define fil_crypt_get_page_throttle(state,offset,mtr,sleeptime_ms) \ fil_crypt_get_page_throttle_func(state, offset, mtr, \ sleeptime_ms, __FILE__, __LINE__) @@ -1709,7 +1709,7 @@ btr_scrub_get_block_and_allocation_status( mtr_start(&local_mtr); - *allocation_status = fsp_page_is_free(space->id, offset, &local_mtr) ? + *allocation_status = fseg_page_is_free(space, offset) ? BTR_SCRUB_PAGE_FREE : BTR_SCRUB_PAGE_ALLOCATED; @@ -1756,9 +1756,9 @@ fil_crypt_rotate_page( ulint offset = state->offset; ulint sleeptime_ms = 0; fil_space_crypt_t *crypt_data = space->crypt_data; - const page_size_t page_size = page_size_t(space->flags); ut_ad(space->n_pending_ops > 0); + ut_ad(offset > 0); /* In fil_crypt_thread where key rotation is done we have acquired space and checked that this space is not yet @@ -1773,44 +1773,55 @@ fil_crypt_rotate_page( return; } + ut_d(const bool was_free = fseg_page_is_free(space, offset)); + mtr_t mtr; mtr.start(); if (buf_block_t* block = fil_crypt_get_page_throttle(state, offset, &mtr, &sleeptime_ms)) { - mtr.set_named_space(space); - bool modified = false; int needs_scrubbing = BTR_SCRUB_SKIP_PAGE; lsn_t block_lsn = block->page.newest_modification; byte* frame = buf_block_get_frame(block); uint kv = mach_read_from_4(frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); - /* check if tablespace is closing after reading page */ - if (!space->is_stopping()) { - - if (kv == 0 && - fil_crypt_is_page_uninitialized(frame, page_size)) { - ; - } else if (fil_crypt_needs_rotation( - crypt_data->encryption, - kv, key_state->key_version, - key_state->rotate_key_age)) { - - modified = true; - - /* force rotation by dummy updating page */ - mlog_write_ulint(frame + - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, - space_id, MLOG_4BYTES, &mtr); - - /* statistics */ - state->crypt_stat.pages_modified++; - } else { - if (crypt_data->is_encrypted()) { - if (kv < state->min_key_version_found) { - state->min_key_version_found = kv; - } + if (space->is_stopping()) { + /* The tablespace is closing (in DROP TABLE or + TRUNCATE TABLE or similar): avoid further access */ + } else if (!*reinterpret_cast<uint32_t*>(FIL_PAGE_OFFSET + + frame)) { + /* It looks like this page was never + allocated. Because key rotation is accessing + pages in a pattern that is unlike the normal + B-tree and undo log access pattern, we cannot + invoke fseg_page_is_free() here, because that + could result in a deadlock. If we invoked + fseg_page_is_free() and released the + tablespace latch before acquiring block->lock, + then the fseg_page_is_free() information + could be stale already. */ + ut_ad(was_free); + ut_ad(kv == 0); + ut_ad(page_get_space_id(frame) == 0); + } else if (fil_crypt_needs_rotation( + crypt_data->encryption, + kv, key_state->key_version, + key_state->rotate_key_age)) { + + mtr.set_named_space(space); + modified = true; + + /* force rotation by dummy updating page */ + mlog_write_ulint(frame + FIL_PAGE_SPACE_ID, + space_id, MLOG_4BYTES, &mtr); + + /* statistics */ + state->crypt_stat.pages_modified++; + } else { + if (crypt_data->is_encrypted()) { + if (kv < state->min_key_version_found) { + state->min_key_version_found = kv; } } @@ -1920,7 +1931,8 @@ fil_crypt_rotate_pages( rotate_thread_t* state) { ulint space = state->space->id; - ulint end = state->offset + state->batch; + ulint end = std::min(state->offset + state->batch, + state->space->free_limit); ut_ad(state->space->n_pending_ops > 0); @@ -2375,7 +2387,10 @@ fil_space_crypt_close_tablespace( ib::warn() << "Waited " << now - start << " seconds to drop space: " - << space->name << "."; + << space->name << " (" + << space->id << ") active threads " + << cnt << "flushing=" + << flushing << "."; last = now; } } |