summaryrefslogtreecommitdiff
path: root/storage/innobase/fil/fil0crypt.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/fil/fil0crypt.cc')
-rw-r--r--storage/innobase/fil/fil0crypt.cc191
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;