summaryrefslogtreecommitdiff
path: root/storage/innobase/fil
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-08-25 10:25:48 +0200
committerSergei Golubchik <serg@mariadb.org>2017-08-25 10:25:48 +0200
commit27412877dbcf601676f4515a99b2abee1f19623b (patch)
tree2cb1a2e1a58ba10f2a96fcdec43f5ed77c326fd0 /storage/innobase/fil
parentf2033df6ac0f64664d9aad2d56fdd74f4bf9d666 (diff)
parenta544225d0a772bd4b67c96f5861ecc0ef7e69bba (diff)
downloadmariadb-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.cc123
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;
}
}