Skip to content

Commit 9505c96

Browse files
committed
MDEV-12428 SIGSEGV in buf_page_decrypt_after_read() during DDL
Also, some MDEV-11738/MDEV-11581 post-push fixes. In MariaDB 10.1, there is no fil_space_t::is_being_truncated field, and the predicates fil_space_t::stop_new_ops and fil_space_t::is_stopping() are interchangeable. I requested the fil_space_t::is_stopping() to be added in the review, but some added checks for fil_space_t::stop_new_ops were not replaced with calls to fil_space_t::is_stopping(). buf_page_decrypt_after_read(): In this low-level I/O operation, we must look up the tablespace if it exists, even though future I/O operations have been blocked on it due to a pending DDL operation, such as DROP TABLE or TRUNCATE TABLE or other table-rebuilding operations (ALTER, OPTIMIZE). Pass a parameter to fil_space_acquire_low() telling that we are performing a low-level I/O operation and the fil_space_t::is_stopping() status should be ignored.
1 parent ac8218a commit 9505c96

File tree

8 files changed

+108
-119
lines changed

8 files changed

+108
-119
lines changed

storage/innobase/btr/btr0scrub.cc

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table,
129129
* if we don't lock to close a table, we check if space
130130
* is closing, and then instead give up
131131
*/
132-
if (lock_to_close_table == false) {
133-
fil_space_t* space = fil_space_acquire(space_id);
134-
if (!space || space->stop_new_ops) {
135-
if (space) {
136-
fil_space_release(space);
137-
}
132+
if (lock_to_close_table) {
133+
} else if (fil_space_t* space = fil_space_acquire(space_id)) {
134+
bool stopping = space->is_stopping();
135+
fil_space_release(space);
136+
if (stopping) {
138137
return false;
139138
}
140-
fil_space_release(space);
139+
} else {
140+
return false;
141141
}
142142
os_thread_sleep(250000);
143143

@@ -197,18 +197,15 @@ btr_scrub_table_close_for_thread(
197197
return;
198198
}
199199

200-
fil_space_t* space = fil_space_acquire(scrub_data->space);
201-
202-
/* If tablespace is not marked as stopping perform
203-
the actual close. */
204-
if (space && !space->is_stopping()) {
205-
mutex_enter(&dict_sys->mutex);
206-
/* perform the actual closing */
207-
btr_scrub_table_close(scrub_data->current_table);
208-
mutex_exit(&dict_sys->mutex);
209-
}
210-
211-
if (space) {
200+
if (fil_space_t* space = fil_space_acquire(scrub_data->space)) {
201+
/* If tablespace is not marked as stopping perform
202+
the actual close. */
203+
if (!space->is_stopping()) {
204+
mutex_enter(&dict_sys->mutex);
205+
/* perform the actual closing */
206+
btr_scrub_table_close(scrub_data->current_table);
207+
mutex_exit(&dict_sys->mutex);
208+
}
212209
fil_space_release(space);
213210
}
214211

storage/innobase/buf/buf0buf.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6250,13 +6250,12 @@ buf_page_decrypt_after_read(
62506250
return (true);
62516251
}
62526252

6253-
fil_space_t* space = fil_space_acquire(bpage->space);
6254-
fil_space_crypt_t* crypt_data = space->crypt_data;
6253+
fil_space_t* space = fil_space_acquire(bpage->space, true);
62556254

62566255
/* Page is encrypted if encryption information is found from
62576256
tablespace and page contains used key_version. This is true
62586257
also for pages first compressed and then encrypted. */
6259-
if (!crypt_data) {
6258+
if (!space || !space->crypt_data) {
62606259
key_version = 0;
62616260
}
62626261

@@ -6340,6 +6339,8 @@ buf_page_decrypt_after_read(
63406339
}
63416340
}
63426341

6343-
fil_space_release(space);
6342+
if (space != NULL) {
6343+
fil_space_release(space);
6344+
}
63446345
return (success);
63456346
}

storage/innobase/fil/fil0fil.cc

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6325,16 +6325,12 @@ fil_flush(
63256325
{
63266326
mutex_enter(&fil_system->mutex);
63276327

6328-
fil_space_t* space = fil_space_get_by_id(space_id);
6329-
6330-
if (!space || space->stop_new_ops) {
6331-
mutex_exit(&fil_system->mutex);
6332-
6333-
return;
6328+
if (fil_space_t* space = fil_space_get_by_id(space_id)) {
6329+
if (!space->is_stopping()) {
6330+
fil_flush_low(space);
6331+
}
63346332
}
63356333

6336-
fil_flush_low(space);
6337-
63386334
mutex_exit(&fil_system->mutex);
63396335
}
63406336

@@ -6374,8 +6370,7 @@ fil_flush_file_spaces(
63746370
space;
63756371
space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
63766372

6377-
if (space->purpose == purpose && !space->stop_new_ops) {
6378-
6373+
if (space->purpose == purpose && !space->is_stopping()) {
63796374
space_ids[n_space_ids++] = space->id;
63806375
}
63816376
}
@@ -7276,12 +7271,13 @@ Used by background threads that do not necessarily hold proper locks
72767271
for concurrency control.
72777272
@param[in] id tablespace ID
72787273
@param[in] silent whether to silently ignore missing tablespaces
7279-
@return the tablespace, or NULL if missing or being deleted */
7274+
@param[in] for_io whether to look up the tablespace while performing I/O
7275+
(possibly executing TRUNCATE)
7276+
@return the tablespace
7277+
@retval NULL if missing or being deleted or truncated */
72807278
inline
72817279
fil_space_t*
7282-
fil_space_acquire_low(
7283-
ulint id,
7284-
bool silent)
7280+
fil_space_acquire_low(ulint id, bool silent, bool for_io = false)
72857281
{
72867282
fil_space_t* space;
72877283

@@ -7294,7 +7290,7 @@ fil_space_acquire_low(
72947290
ib_logf(IB_LOG_LEVEL_WARN, "Trying to access missing"
72957291
" tablespace " ULINTPF ".", id);
72967292
}
7297-
} else if (space->stop_new_ops) {
7293+
} else if (!for_io && space->is_stopping()) {
72987294
space = NULL;
72997295
} else {
73007296
space->n_pending_ops++;
@@ -7309,31 +7305,32 @@ fil_space_acquire_low(
73097305
Used by background threads that do not necessarily hold proper locks
73107306
for concurrency control.
73117307
@param[in] id tablespace ID
7312-
@return the tablespace, or NULL if missing or being deleted */
7308+
@param[in] for_io whether to look up the tablespace while performing I/O
7309+
(possibly executing TRUNCATE)
7310+
@return the tablespace
7311+
@retval NULL if missing or being deleted or truncated */
73137312
fil_space_t*
7314-
fil_space_acquire(
7315-
ulint id)
7313+
fil_space_acquire(ulint id, bool for_io)
73167314
{
7317-
return(fil_space_acquire_low(id, false));
7315+
return(fil_space_acquire_low(id, false, for_io));
73187316
}
73197317

73207318
/** Acquire a tablespace that may not exist.
73217319
Used by background threads that do not necessarily hold proper locks
73227320
for concurrency control.
73237321
@param[in] id tablespace ID
7324-
@return the tablespace, or NULL if missing or being deleted */
7322+
@return the tablespace
7323+
@retval NULL if missing or being deleted */
73257324
fil_space_t*
7326-
fil_space_acquire_silent(
7327-
ulint id)
7325+
fil_space_acquire_silent(ulint id)
73287326
{
73297327
return(fil_space_acquire_low(id, true));
73307328
}
73317329

73327330
/** Release a tablespace acquired with fil_space_acquire().
73337331
@param[in,out] space tablespace to release */
73347332
void
7335-
fil_space_release(
7336-
fil_space_t* space)
7333+
fil_space_release(fil_space_t* space)
73377334
{
73387335
mutex_enter(&fil_system->mutex);
73397336
ut_ad(space->magic_n == FIL_SPACE_MAGIC_N);
@@ -7351,8 +7348,7 @@ If NULL, use the first fil_space_t on fil_system->space_list.
73517348
@return pointer to the next fil_space_t.
73527349
@retval NULL if this was the last*/
73537350
fil_space_t*
7354-
fil_space_next(
7355-
fil_space_t* prev_space)
7351+
fil_space_next(fil_space_t* prev_space)
73567352
{
73577353
fil_space_t* space=prev_space;
73587354

@@ -7375,8 +7371,8 @@ fil_space_next(
73757371
fil_ibd_create(), or dropped, or !tablespace. */
73767372
while (space != NULL
73777373
&& (UT_LIST_GET_LEN(space->chain) == 0
7378-
|| space->stop_new_ops
7379-
|| space->purpose != FIL_TABLESPACE)) {
7374+
|| space->is_stopping()
7375+
|| space->purpose != FIL_TABLESPACE)) {
73807376
space = UT_LIST_GET_NEXT(space_list, space);
73817377
}
73827378

storage/innobase/include/fil0fil.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -645,27 +645,28 @@ fil_write_flushed_lsn_to_data_files(
645645
Used by background threads that do not necessarily hold proper locks
646646
for concurrency control.
647647
@param[in] id tablespace ID
648-
@return the tablespace, or NULL if missing or being deleted */
648+
@param[in] for_io whether to look up the tablespace while performing I/O
649+
(possibly executing TRUNCATE)
650+
@return the tablespace
651+
@retval NULL if missing or being deleted or truncated */
649652
fil_space_t*
650-
fil_space_acquire(
651-
ulint id)
653+
fil_space_acquire(ulint id, bool for_io = false)
652654
MY_ATTRIBUTE((warn_unused_result));
653655

654656
/** Acquire a tablespace that may not exist.
655657
Used by background threads that do not necessarily hold proper locks
656658
for concurrency control.
657659
@param[in] id tablespace ID
658-
@return the tablespace, or NULL if missing or being deleted */
660+
@return the tablespace
661+
@retval NULL if missing or being deleted */
659662
fil_space_t*
660-
fil_space_acquire_silent(
661-
ulint id)
663+
fil_space_acquire_silent(ulint id)
662664
MY_ATTRIBUTE((warn_unused_result));
663665

664666
/** Release a tablespace acquired with fil_space_acquire().
665667
@param[in,out] space tablespace to release */
666668
void
667-
fil_space_release(
668-
fil_space_t* space);
669+
fil_space_release(fil_space_t* space);
669670

670671
/** Return the next fil_space_t.
671672
Once started, the caller must keep calling this until it returns NULL.

storage/xtradb/btr/btr0scrub.cc

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table,
129129
* if we don't lock to close a table, we check if space
130130
* is closing, and then instead give up
131131
*/
132-
if (lock_to_close_table == false) {
133-
fil_space_t* space = fil_space_acquire(space_id);
134-
if (!space || space->stop_new_ops) {
135-
if (space) {
136-
fil_space_release(space);
137-
}
132+
if (lock_to_close_table) {
133+
} else if (fil_space_t* space = fil_space_acquire(space_id)) {
134+
bool stopping = space->is_stopping();
135+
fil_space_release(space);
136+
if (stopping) {
138137
return false;
139138
}
140-
fil_space_release(space);
139+
} else {
140+
return false;
141141
}
142142
os_thread_sleep(250000);
143143

@@ -197,18 +197,15 @@ btr_scrub_table_close_for_thread(
197197
return;
198198
}
199199

200-
fil_space_t* space = fil_space_acquire(scrub_data->space);
201-
202-
/* If tablespace is not marked as stopping perform
203-
the actual close. */
204-
if (space && !space->is_stopping()) {
205-
mutex_enter(&dict_sys->mutex);
206-
/* perform the actual closing */
207-
btr_scrub_table_close(scrub_data->current_table);
208-
mutex_exit(&dict_sys->mutex);
209-
}
210-
211-
if (space) {
200+
if (fil_space_t* space = fil_space_acquire(scrub_data->space)) {
201+
/* If tablespace is not marked as stopping perform
202+
the actual close. */
203+
if (!space->is_stopping()) {
204+
mutex_enter(&dict_sys->mutex);
205+
/* perform the actual closing */
206+
btr_scrub_table_close(scrub_data->current_table);
207+
mutex_exit(&dict_sys->mutex);
208+
}
212209
fil_space_release(space);
213210
}
214211

storage/xtradb/buf/buf0buf.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6410,14 +6410,12 @@ buf_page_decrypt_after_read(
64106410
return (true);
64116411
}
64126412

6413-
fil_space_t* space = fil_space_acquire(bpage->space);
6414-
6415-
fil_space_crypt_t* crypt_data = space->crypt_data;
6413+
fil_space_t* space = fil_space_acquire(bpage->space, true);
64166414

64176415
/* Page is encrypted if encryption information is found from
64186416
tablespace and page contains used key_version. This is true
64196417
also for pages first compressed and then encrypted. */
6420-
if (!crypt_data) {
6418+
if (!space || !space->crypt_data) {
64216419
key_version = 0;
64226420
}
64236421

@@ -6501,6 +6499,8 @@ buf_page_decrypt_after_read(
65016499
}
65026500
}
65036501

6504-
fil_space_release(space);
6502+
if (space != NULL) {
6503+
fil_space_release(space);
6504+
}
65056505
return (success);
65066506
}

0 commit comments

Comments
 (0)