diff options
Diffstat (limited to 'storage/innobase/fil/fil0crypt.cc')
-rw-r--r-- | storage/innobase/fil/fil0crypt.cc | 191 |
1 files changed, 108 insertions, 83 deletions
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index f68eabba579..b4c273299f3 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -95,17 +95,6 @@ extern uint srv_background_scrub_data_check_interval; static fil_crypt_stat_t crypt_stat; static ib_mutex_t crypt_stat_mutex; -#ifdef UNIV_PFS_MUTEX -UNIV_INTERN mysql_pfs_key_t fil_crypt_stat_mutex_key; -#endif - -/** - * key for crypt data mutex -*/ -#ifdef UNIV_PFS_MUTEX -UNIV_INTERN mysql_pfs_key_t fil_crypt_data_mutex_key; -#endif - static bool fil_crypt_needs_rotation( /*=====================*/ @@ -142,6 +131,23 @@ fil_space_crypt_cleanup() mutex_free(&crypt_stat_mutex); } +/** +Get latest key version from encryption plugin. +@return key version or ENCRYPTION_KEY_VERSION_INVALID */ +uint +fil_space_crypt_struct::key_get_latest_version(void) +{ + uint key_version = key_found; + + if (is_key_found()) { + key_version = encryption_key_get_latest_version(key_id); + srv_stats.n_key_requests.inc(); + key_found = key_version; + } + + return key_version; +} + /****************************************************************** Get the latest(key-version), waking the encrypt thread, if needed */ static inline @@ -150,20 +156,25 @@ fil_crypt_get_latest_key_version( /*=============================*/ fil_space_crypt_t* crypt_data) /*!< in: crypt data */ { - uint rc = encryption_key_get_latest_version(crypt_data->key_id); + ut_ad(crypt_data != NULL); - if (fil_crypt_needs_rotation(crypt_data->encryption, - crypt_data->min_key_version, - rc, srv_fil_crypt_rotate_key_age)) { - os_event_set(fil_crypt_threads_event); + uint key_version = crypt_data->key_get_latest_version(); + + if (crypt_data->is_key_found()) { + + if (fil_crypt_needs_rotation(crypt_data->encryption, + crypt_data->min_key_version, + key_version, + srv_fil_crypt_rotate_key_age)) { + os_event_set(fil_crypt_threads_event); + } } - return rc; + return key_version; } /****************************************************************** Mutex helper for crypt_data->scheme */ -static void crypt_data_scheme_locker( /*=====================*/ @@ -183,37 +194,47 @@ crypt_data_scheme_locker( /****************************************************************** Create a fil_space_crypt_t object @return crypt object */ -UNIV_INTERN +static fil_space_crypt_t* fil_space_create_crypt_data( /*========================*/ - fil_encryption_t encrypt_mode, /*!< in: encryption mode */ - uint key_id) /*!< in: encryption key id */ + uint type, + fil_encryption_t encrypt_mode, + uint min_key_version, + uint key_id, + ulint offset) { const uint sz = sizeof(fil_space_crypt_t); - fil_space_crypt_t* crypt_data = - static_cast<fil_space_crypt_t*>(malloc(sz)); - - memset(crypt_data, 0, sz); + void* buf = ut_zalloc_nokey(sz); + fil_space_crypt_t* crypt_data = NULL; - if (encrypt_mode == FIL_SPACE_ENCRYPTION_OFF || - (!srv_encrypt_tables && encrypt_mode == FIL_SPACE_ENCRYPTION_DEFAULT)) { - crypt_data->type = CRYPT_SCHEME_UNENCRYPTED; - } else { - crypt_data->type = CRYPT_SCHEME_1; - crypt_data->min_key_version = encryption_key_get_latest_version(key_id); + if (buf) { + crypt_data = new(buf) + fil_space_crypt_struct( + type, + min_key_version, + key_id, + offset, + encrypt_mode); } - mutex_create(LATCH_ID_FIL_CRYPT_DATA_MUTEX, &crypt_data->mutex); - crypt_data->locker = crypt_data_scheme_locker; - my_random_bytes(crypt_data->iv, sizeof(crypt_data->iv)); - crypt_data->encryption = encrypt_mode; - crypt_data->inited = true; - crypt_data->key_id = key_id; return crypt_data; } /****************************************************************** +Create a fil_space_crypt_t object +@return crypt object */ +UNIV_INTERN +fil_space_crypt_t* +fil_space_create_crypt_data( +/*========================*/ + fil_encryption_t encrypt_mode, /*!< in: encryption mode */ + uint key_id) /*!< in: encryption key id */ +{ + return (fil_space_create_crypt_data(0, encrypt_mode, 0, key_id, 0)); +} + +/****************************************************************** Merge fil_space_crypt_t object */ UNIV_INTERN void @@ -235,7 +256,7 @@ fil_space_merge_crypt_data( dst->type = src->type; dst->min_key_version = src->min_key_version; dst->keyserver_requests += src->keyserver_requests; - dst->inited = src->inited; + dst->closing = src->closing; mutex_exit(&dst->mutex); } @@ -302,18 +323,12 @@ fil_space_read_crypt_data( fil_encryption_t encryption = (fil_encryption_t)mach_read_from_1( page + offset + MAGIC_SZ + 2 + iv_length + 8); - const uint sz = sizeof(fil_space_crypt_t) + iv_length; - crypt_data = static_cast<fil_space_crypt_t*>(malloc(sz)); - memset(crypt_data, 0, sz); - + crypt_data = fil_space_create_crypt_data(encryption, key_id); + /* We need to overwrite these as above function will initialize + members */ crypt_data->type = type; crypt_data->min_key_version = min_key_version; - crypt_data->key_id = key_id; crypt_data->page0_offset = offset; - crypt_data->encryption = encryption; - mutex_create(LATCH_ID_FIL_CRYPT_DATA_MUTEX, &crypt_data->mutex); - crypt_data->locker = crypt_data_scheme_locker; - crypt_data->inited = true; memcpy(crypt_data->iv, page + offset + MAGIC_SZ + 2, iv_length); return crypt_data; @@ -328,12 +343,10 @@ fil_space_destroy_crypt_data( fil_space_crypt_t **crypt_data) /*!< out: crypt data */ { if (crypt_data != NULL && (*crypt_data) != NULL) { - /* Make sure that this thread owns the crypt_data - and make it unawailable, this does not fully - avoid the race between drop table and crypt thread */ mutex_enter(&fil_crypt_threads_mutex); - mutex_free(&(*crypt_data)->mutex); - free(*crypt_data); + fil_space_crypt_t* c = *crypt_data; + c->~fil_space_crypt_struct(); + ut_free(c); *crypt_data = NULL; mutex_exit(&fil_crypt_threads_mutex); } @@ -482,6 +495,7 @@ fil_parse_write_crypt_data( } fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(encryption, key_id); + /* Need to overwrite these as above will initialize fields. */ crypt_data->page0_offset = offset; crypt_data->min_key_version = min_key_version; crypt_data->encryption = encryption; @@ -635,7 +649,7 @@ fil_space_encrypt( return src_frame; } - ut_a(crypt_data != NULL && crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + ut_a(crypt_data != NULL && crypt_data->is_encrypted()); byte* tmp = fil_encrypt_buf(crypt_data, space, offset, lsn, src_frame, page_size, dst_frame); @@ -714,7 +728,7 @@ fil_space_check_encryption_read( return false; } - if (crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) { + if (crypt_data->not_encrypted()) { return false; } @@ -767,7 +781,7 @@ fil_space_decrypt( return false; } - ut_a(crypt_data != NULL && crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + ut_a(crypt_data != NULL && crypt_data->is_encrypted()); /* read space & lsn */ ulint header_len = FIL_PAGE_DATA; @@ -999,20 +1013,13 @@ Copy global key state */ static void fil_crypt_get_key_state( /*====================*/ - key_state_t *new_state) /*!< out: key state */ + key_state_t* new_state, /*!< out: key state */ + fil_space_crypt_t* crypt_data) /*!< in, out: crypt_data */ { if (srv_encrypt_tables) { - new_state->key_version = - encryption_key_get_latest_version(new_state->key_id); + new_state->key_version = crypt_data->key_get_latest_version(); new_state->rotate_key_age = srv_fil_crypt_rotate_key_age; - if (new_state->key_version == ENCRYPTION_KEY_VERSION_INVALID) { - ib::error() << "Used key_id " - << new_state->key_id - << " can't be found from key file."; - } - - ut_a(new_state->key_version != ENCRYPTION_KEY_VERSION_INVALID); ut_a(new_state->key_version != ENCRYPTION_KEY_NOT_ENCRYPTED); } else { new_state->key_version = 0; @@ -1072,9 +1079,7 @@ fil_crypt_is_closing( fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space); if (crypt_data) { - mutex_enter(&crypt_data->mutex); - closing = crypt_data->closing; - mutex_exit(&crypt_data->mutex); + closing = crypt_data->is_closing(false); } return closing; @@ -1333,6 +1338,18 @@ fil_crypt_space_needs_rotation( } return false; } + + crypt_data->key_get_latest_version(); + + if (!crypt_data->is_key_found()) { + return false; + } + } + + /* If used key_id is not found from encryption plugin we can't + continue to rotate the tablespace */ + if (!crypt_data->is_key_found()) { + return false; } mutex_enter(&crypt_data->mutex); @@ -1346,7 +1363,7 @@ fil_crypt_space_needs_rotation( } /* prevent threads from starting to rotate space */ - if (crypt_data->closing) { + if (crypt_data->is_closing(true)) { break; } @@ -1355,13 +1372,13 @@ fil_crypt_space_needs_rotation( } /* No need to rotate space if encryption is disabled */ - if (crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) { + if (crypt_data->not_encrypted()) { break; } if (crypt_data->key_id != key_state->key_id) { key_state->key_id= crypt_data->key_id; - fil_crypt_get_key_state(key_state); + fil_crypt_get_key_state(key_state, crypt_data); } bool need_key_rotation = fil_crypt_needs_rotation( @@ -1374,12 +1391,14 @@ fil_crypt_space_needs_rotation( time_t diff = time(0) - crypt_data->rotate_state.scrubbing. last_scrub_completed; + bool need_scrubbing = crypt_data->rotate_state.scrubbing.is_active && diff >= (time_t) srv_background_scrub_data_interval; - if (need_key_rotation == false && need_scrubbing == false) + if (need_key_rotation == false && need_scrubbing == false) { break; + } mutex_exit(&crypt_data->mutex); /* NOTE! fil_decr_pending_ops is performed outside */ @@ -1595,8 +1614,9 @@ fil_crypt_find_space_to_rotate( os_event_wait_time(fil_crypt_threads_event, 1000000); } - if (state->should_shutdown()) + if (state->should_shutdown()) { return false; + } if (state->first) { state->first = false; @@ -1658,7 +1678,7 @@ fil_crypt_start_rotate_space( crypt_data->rotate_state.start_time = time(0); if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED && - crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF && + crypt_data->is_encrypted() && key_state->key_version != 0) { /* this is rotation unencrypted => encrypted */ crypt_data->type = CRYPT_SCHEME_1; @@ -1695,7 +1715,7 @@ fil_crypt_find_page_to_rotate( mutex_enter(&crypt_data->mutex); ut_ad(key_state->key_id == crypt_data->key_id); - if (crypt_data->closing == false && + if (!crypt_data->is_closing(true) && crypt_data->rotate_state.next_offset < crypt_data->rotate_state.max_offset) { @@ -1959,7 +1979,7 @@ fil_crypt_rotate_page( /* statistics */ state->crypt_stat.pages_modified++; } else { - if (crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF) { + if (crypt_data->is_encrypted()) { ut_a(kv >= crypt_data->min_key_version || (kv == 0 && key_state->key_version == 0)); @@ -2172,7 +2192,7 @@ fil_crypt_complete_rotate_space( fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space); /* Space might already be dropped */ - if (crypt_data != NULL && crypt_data->inited) { + if (crypt_data != NULL && !crypt_data->is_closing(false)) { mutex_enter(&crypt_data->mutex); /** @@ -2469,7 +2489,8 @@ UNIV_INTERN void fil_space_crypt_mark_space_closing( /*===============================*/ - ulint space) /*!< in: Space id */ + ulint space, /*!< in: tablespace id */ + fil_space_crypt_t* crypt_data) /*!< in: crypt_data or NULL */ { if (!fil_crypt_threads_inited) { return; @@ -2477,7 +2498,9 @@ fil_space_crypt_mark_space_closing( mutex_enter(&fil_crypt_threads_mutex); - fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); + if (!crypt_data) { + crypt_data = fil_space_get_crypt_data(space); + } if (crypt_data == NULL) { mutex_exit(&fil_crypt_threads_mutex); @@ -2506,7 +2529,7 @@ fil_space_crypt_close_tablespace( fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); - if (crypt_data == NULL || !crypt_data->inited) { + if (crypt_data == NULL || crypt_data->is_closing(false)) { mutex_exit(&fil_crypt_threads_mutex); return; } @@ -2560,6 +2583,8 @@ fil_space_crypt_get_status( { fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id); + memset(status, 0, sizeof(*status)); + if (crypt_data != NULL) { status->space = id; status->scheme = crypt_data->type; @@ -2580,6 +2605,7 @@ fil_space_crypt_get_status( } else { status->rotating = false; } + mutex_exit(&crypt_data->mutex); if (srv_encrypt_tables || crypt_data->min_key_version) { @@ -2589,7 +2615,6 @@ fil_space_crypt_get_status( status->current_key_version = 0; } } else { - memset(status, 0, sizeof(*status)); if (srv_encrypt_tables) { os_event_set(fil_crypt_threads_event); } @@ -2622,6 +2647,7 @@ fil_space_get_scrub_status( struct fil_space_scrub_status_t* status) /*!< out: status */ { fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id); + memset(status, 0, sizeof(*status)); if (crypt_data != NULL) { @@ -2646,9 +2672,8 @@ fil_space_get_scrub_status( } else { status->scrubbing = false; } + mutex_exit(&crypt_data->mutex); - } else { - memset(status, 0, sizeof(*status)); } return crypt_data == NULL ? 1 : 0; |