Skip to content

Commit 41afe38

Browse files
MDEV-34358 Detect config changes during encryption iteration
Problem: ======= When innodb_encrypt_tables or innodb_encryption_rotate_key_age is changed during encryption thread iteration, threads continue with stale configuration values, potentially missing tablespaces that should be encrypted or rotated under the new settings. Solution: ======== Added atomic version counter fil_crypt_settings_version that is incremented whenever innodb_encrypt_tables or innodb_encryption_rotate_key_age changes. Encryption threads capture the version at iteration start and check for changes during iteration. If config changed, threads immediately restart iteration from the beginning to ensure complete coverage with new settings. fil_crypt_settings_version: Atomic counter to track the innodb_encrypt_tables or innodb_encryption_rotate_key_age changes rotate_thread_t::settings_version: To compare the existing fil_crypt_settings_version to restart the encryption from the beginning
1 parent 67e8b4f commit 41afe38

1 file changed

Lines changed: 44 additions & 3 deletions

File tree

storage/innobase/fil/fil0crypt.cc

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ static bool fil_crypt_threads_inited = false;
4646
/** Is encryption enabled/disabled */
4747
ulong srv_encrypt_tables;
4848

49+
/** Version counter for innodb_encrypt_tables changes.
50+
Incremented each time innodb_encrypt_tables or
51+
innodb_encryption_rotate_key_age is modified to signal
52+
encryption threads to restart iteration */
53+
static Atomic_counter<uint16_t> fil_crypt_settings_version;
54+
4955
/** No of key rotation threads requested */
5056
uint srv_n_fil_crypt_threads;
5157

@@ -1029,7 +1035,8 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space)
10291035

10301036
/** State of a rotation thread */
10311037
struct rotate_thread_t {
1032-
explicit rotate_thread_t(uint no) : thread_no(no) {}
1038+
explicit rotate_thread_t(uint no) : thread_no(no),
1039+
settings_version(fil_crypt_settings_version) {}
10331040

10341041
bool first = true; /*!< is position before first space */
10351042

@@ -1052,6 +1059,11 @@ struct rotate_thread_t {
10521059
when woken by signal or when work is found. */
10531060
uint16_t sleep_timeout_ms= 5000;
10541061

1062+
/** Config version when thread started current iteration.
1063+
Used to detect innodb_encrypt_tables changes during iteration
1064+
and restart from beginning to ensure complete encryption coverage. */
1065+
uint16_t settings_version;
1066+
10551067
uint thread_no;
10561068
uint32_t offset = 0; /*!< current page number */
10571069
uint min_key_version_found = 0; /*!< min key version found but not rotated */
@@ -1083,6 +1095,12 @@ struct rotate_thread_t {
10831095
timed_wait_count = 0;
10841096
}
10851097

1098+
/** Check if innodb_encrypt_tables config has changed.
1099+
@return true if config changed, requiring iteration restart */
1100+
bool settings_changed() const {
1101+
return settings_version != fil_crypt_settings_version;
1102+
}
1103+
10861104
/** @return whether this thread should terminate */
10871105
bool should_shutdown() const {
10881106
mysql_mutex_assert_owner(&fil_crypt_threads_mutex);
@@ -2137,23 +2155,39 @@ static void fil_crypt_thread()
21372155
/* if we find a tablespace that is starting, skip over it
21382156
and recheck it later */
21392157
bool recheck = false;
2140-
21412158
wait_for_work:
21422159
thr.wait_for_work(recheck);
21432160

2161+
restart_iteration:
21442162
recheck = false;
21452163
thr.first = true; // restart from first tablespace
2164+
thr.settings_version = fil_crypt_settings_version;
21462165
key_state_t new_state;
21472166

21482167
/* iterate all spaces searching for those needing rotation */
21492168
while (fil_crypt_find_space_to_rotate(&new_state, &thr,
21502169
&recheck)) {
2170+
#if 0
2171+
/* Check if innodb_encrypt_tables or
2172+
innodb_encryption_rotate_key_age changed during
2173+
iteration. If changed, restart immediately */
2174+
if (thr.settings_changed()) {
2175+
2176+
if (thr.space != fil_system.space_list.end() &&
2177+
thr.space != space_list_t::iterator(
2178+
fil_system.temp_space)) {
2179+
thr.space->release();
2180+
}
21512181

2182+
thr.space = fil_system.space_list.end();
2183+
goto restart_iteration;
2184+
}
2185+
#endif
21522186
if (thr.space == fil_system.space_list.end()) {
21532187
/* When iterating fil_system.space_list,
21542188
reaching .end(), it could mean all spaces
21552189
are encrypted, or some spaces were temporarily
2156-
unacquirable (CLOSING flag, DDL in progress).
2190+
unacquirable (CLOSING flag, DDL in progress).
21572191
21582192
For default_encrypt_list: Spaces exist but
21592193
none are acquirable. Wake other threads
@@ -2329,6 +2363,10 @@ void fil_crypt_set_rotate_key_age(uint val)
23292363
if (val == 0)
23302364
fil_crypt_default_encrypt_tables_fill();
23312365
mysql_mutex_unlock(&fil_system.mutex);
2366+
2367+
/* Increment version to signal threads to restart iteration */
2368+
fil_crypt_settings_version++;
2369+
23322370
pthread_cond_broadcast(&fil_crypt_threads_cond);
23332371
mysql_mutex_unlock(&fil_crypt_threads_mutex);
23342372
}
@@ -2383,6 +2421,9 @@ void fil_crypt_set_encrypt_tables(ulong val)
23832421

23842422
mysql_mutex_unlock(&fil_system.mutex);
23852423

2424+
/* Increment version to signal threads to restart iteration */
2425+
fil_crypt_settings_version++;
2426+
23862427
pthread_cond_broadcast(&fil_crypt_threads_cond);
23872428
mysql_mutex_unlock(&fil_crypt_threads_mutex);
23882429
}

0 commit comments

Comments
 (0)