Commit 925b6412 authored by Jan Lindström's avatar Jan Lindström

MDEV-8182: Failing assertion: 1 == UT_LIST_GET_LEN(space->chain)

Analysis: At fil_spage_get_space there is small change that space
is found from tablespace list but we have not yet created node
for it (and added it to space->chain) and as we hold fil_system
mutex here fil_node_create can't continue.

Fixed by allowing UT_LIST_GET_LEN(space->chain) == 0|| 1 and
introducint two new functions that access filespace list
and before returning space check that node is also created.
parent 3e55ef26
...@@ -1510,9 +1510,9 @@ fil_crypt_find_space_to_rotate( ...@@ -1510,9 +1510,9 @@ fil_crypt_find_space_to_rotate(
if (state->first) { if (state->first) {
state->first = false; state->first = false;
state->space = fil_get_first_space(); state->space = fil_get_first_space_safe();
} else { } else {
state->space = fil_get_next_space(state->space); state->space = fil_get_next_space_safe(state->space);
} }
while (!state->should_shutdown() && state->space != ULINT_UNDEFINED) { while (!state->should_shutdown() && state->space != ULINT_UNDEFINED) {
...@@ -1525,7 +1525,7 @@ fil_crypt_find_space_to_rotate( ...@@ -1525,7 +1525,7 @@ fil_crypt_find_space_to_rotate(
return true; return true;
} }
state->space = fil_get_next_space(state->space); state->space = fil_get_next_space_safe(state->space);
} }
/* if we didn't find any space return iops */ /* if we didn't find any space return iops */
...@@ -2047,7 +2047,6 @@ fil_crypt_complete_rotate_space( ...@@ -2047,7 +2047,6 @@ fil_crypt_complete_rotate_space(
/* Space might already be dropped */ /* Space might already be dropped */
if (crypt_data) { if (crypt_data) {
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
/** /**
...@@ -2096,6 +2095,7 @@ fil_crypt_complete_rotate_space( ...@@ -2096,6 +2095,7 @@ fil_crypt_complete_rotate_space(
if (btr_scrub_complete_space(&state->scrub_data) == true) { if (btr_scrub_complete_space(&state->scrub_data) == true) {
if (should_flush) { if (should_flush) {
/* only last thread updates last_scrub_completed */ /* only last thread updates last_scrub_completed */
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing. crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0); last_scrub_completed = time(0);
...@@ -2106,6 +2106,7 @@ fil_crypt_complete_rotate_space( ...@@ -2106,6 +2106,7 @@ fil_crypt_complete_rotate_space(
if (should_flush) { if (should_flush) {
fil_crypt_flush_space(state, space); fil_crypt_flush_space(state, space);
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.flushing = false; crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
......
...@@ -1408,21 +1408,26 @@ fil_space_get_space( ...@@ -1408,21 +1408,26 @@ fil_space_get_space(
} }
/* The following code must change when InnoDB supports /* The following code must change when InnoDB supports
multiple datafiles per tablespace. */ multiple datafiles per tablespace. Note that there is small
ut_a(1 == UT_LIST_GET_LEN(space->chain)); change that space is found from tablespace list but
we have not yet created node for it and as we hold
fil_system mutex here fil_node_create can't continue. */
ut_a(UT_LIST_GET_LEN(space->chain) == 1 || UT_LIST_GET_LEN(space->chain) == 0);
node = UT_LIST_GET_FIRST(space->chain); node = UT_LIST_GET_FIRST(space->chain);
/* It must be a single-table tablespace and we have not opened if (node) {
the file yet; the following calls will open it and update the /* It must be a single-table tablespace and we have not opened
size fields */ the file yet; the following calls will open it and update the
size fields */
if (!fil_node_prepare_for_io(node, fil_system, space)) {
/* The single-table tablespace can't be opened, if (!fil_node_prepare_for_io(node, fil_system, space)) {
because the ibd file is missing. */ /* The single-table tablespace can't be opened,
return(NULL); because the ibd file is missing. */
return(NULL);
}
fil_node_complete_io(node, fil_system, OS_FILE_READ);
} }
fil_node_complete_io(node, fil_system, OS_FILE_READ);
} }
return(space); return(space);
...@@ -6764,6 +6769,7 @@ Get id of first tablespace or ULINT_UNDEFINED if none */ ...@@ -6764,6 +6769,7 @@ Get id of first tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_first_space() fil_get_first_space()
/*=================*/
{ {
ulint out_id = ULINT_UNDEFINED; ulint out_id = ULINT_UNDEFINED;
fil_space_t* space; fil_space_t* space;
...@@ -6787,11 +6793,84 @@ fil_get_first_space() ...@@ -6787,11 +6793,84 @@ fil_get_first_space()
return out_id; return out_id;
} }
/******************************************************************
Get id of first tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_first_space_safe()
/*======================*/
{
ulint out_id = ULINT_UNDEFINED;
fil_space_t* space;
mutex_enter(&fil_system->mutex);
space = UT_LIST_GET_FIRST(fil_system->space_list);
if (space != NULL) {
do
{
if (!space->stop_new_ops && UT_LIST_GET_LEN(space->chain) > 0) {
out_id = space->id;
break;
}
space = UT_LIST_GET_NEXT(space_list, space);
} while (space != NULL);
}
mutex_exit(&fil_system->mutex);
return out_id;
}
/****************************************************************** /******************************************************************
Get id of next tablespace or ULINT_UNDEFINED if none */ Get id of next tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_next_space(ulint id) fil_get_next_space(
/*===============*/
ulint id) /*!< in: previous space id */
{
bool found;
fil_space_t* space;
ulint out_id = ULINT_UNDEFINED;
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(id);
if (space == NULL) {
/* we didn't find it...search for space with space->id > id */
found = false;
space = UT_LIST_GET_FIRST(fil_system->space_list);
} else {
/* we found it, take next available space */
found = true;
}
while ((space = UT_LIST_GET_NEXT(space_list, space)) != NULL) {
if (!found && space->id <= id)
continue;
if (!space->stop_new_ops && UT_LIST_GET_LEN(space->chain) > 0) {
/* inc reference to prevent drop */
out_id = space->id;
break;
}
}
mutex_exit(&fil_system->mutex);
return out_id;
}
/******************************************************************
Get id of next tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_next_space_safe(
/*====================*/
ulint id) /*!< in: previous space id */
{ {
bool found; bool found;
fil_space_t* space; fil_space_t* space;
...@@ -6831,7 +6910,7 @@ Get crypt data for a tablespace */ ...@@ -6831,7 +6910,7 @@ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
fil_space_crypt_t* fil_space_crypt_t*
fil_space_get_crypt_data( fil_space_get_crypt_data(
/*==================*/ /*=====================*/
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
{ {
fil_space_t* space; fil_space_t* space;
......
...@@ -1264,14 +1264,32 @@ Get id of first tablespace or ULINT_UNDEFINED if none */ ...@@ -1264,14 +1264,32 @@ Get id of first tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_first_space(); fil_get_first_space();
/*=================*/
/****************************************************************** /******************************************************************
Get id of next tablespace or ULINT_UNDEFINED if none */ Get id of next tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_next_space( fil_get_next_space(
/*===============*/
ulint id); /*!< in: space id */ ulint id); /*!< in: space id */
/******************************************************************
Get id of first tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_first_space_safe();
/*======================*/
/******************************************************************
Get id of next tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_next_space_safe(
/*====================*/
ulint id); /*!< in: previous space id */
#endif /* UNIV_INNOCHECKSUM */
/*******************************************************************//** /*******************************************************************//**
Returns the block size of the file space Returns the block size of the file space
@return block size */ @return block size */
......
...@@ -1510,9 +1510,9 @@ fil_crypt_find_space_to_rotate( ...@@ -1510,9 +1510,9 @@ fil_crypt_find_space_to_rotate(
if (state->first) { if (state->first) {
state->first = false; state->first = false;
state->space = fil_get_first_space(); state->space = fil_get_first_space_safe();
} else { } else {
state->space = fil_get_next_space(state->space); state->space = fil_get_next_space_safe(state->space);
} }
while (!state->should_shutdown() && state->space != ULINT_UNDEFINED) { while (!state->should_shutdown() && state->space != ULINT_UNDEFINED) {
...@@ -1525,7 +1525,7 @@ fil_crypt_find_space_to_rotate( ...@@ -1525,7 +1525,7 @@ fil_crypt_find_space_to_rotate(
return true; return true;
} }
state->space = fil_get_next_space(state->space); state->space = fil_get_next_space_safe(state->space);
} }
/* if we didn't find any space return iops */ /* if we didn't find any space return iops */
...@@ -2047,7 +2047,6 @@ fil_crypt_complete_rotate_space( ...@@ -2047,7 +2047,6 @@ fil_crypt_complete_rotate_space(
/* Space might already be dropped */ /* Space might already be dropped */
if (crypt_data) { if (crypt_data) {
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
/** /**
...@@ -2096,6 +2095,7 @@ fil_crypt_complete_rotate_space( ...@@ -2096,6 +2095,7 @@ fil_crypt_complete_rotate_space(
if (btr_scrub_complete_space(&state->scrub_data) == true) { if (btr_scrub_complete_space(&state->scrub_data) == true) {
if (should_flush) { if (should_flush) {
/* only last thread updates last_scrub_completed */ /* only last thread updates last_scrub_completed */
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing. crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0); last_scrub_completed = time(0);
...@@ -2106,6 +2106,7 @@ fil_crypt_complete_rotate_space( ...@@ -2106,6 +2106,7 @@ fil_crypt_complete_rotate_space(
if (should_flush) { if (should_flush) {
fil_crypt_flush_space(state, space); fil_crypt_flush_space(state, space);
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.flushing = false; crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
......
...@@ -1445,21 +1445,26 @@ fil_space_get_space( ...@@ -1445,21 +1445,26 @@ fil_space_get_space(
} }
/* The following code must change when InnoDB supports /* The following code must change when InnoDB supports
multiple datafiles per tablespace. */ multiple datafiles per tablespace. Note that there is small
ut_a(1 == UT_LIST_GET_LEN(space->chain)); change that space is found from tablespace list but
we have not yet created node for it and as we hold
fil_system mutex here fil_node_create can't continue. */
ut_a(UT_LIST_GET_LEN(space->chain) == 1 || UT_LIST_GET_LEN(space->chain) == 0);
node = UT_LIST_GET_FIRST(space->chain); node = UT_LIST_GET_FIRST(space->chain);
/* It must be a single-table tablespace and we have not opened if (node) {
the file yet; the following calls will open it and update the /* It must be a single-table tablespace and we have not opened
size fields */ the file yet; the following calls will open it and update the
size fields */
if (!fil_node_prepare_for_io(node, fil_system, space)) {
/* The single-table tablespace can't be opened, if (!fil_node_prepare_for_io(node, fil_system, space)) {
because the ibd file is missing. */ /* The single-table tablespace can't be opened,
return(NULL); because the ibd file is missing. */
return(NULL);
}
fil_node_complete_io(node, fil_system, OS_FILE_READ);
} }
fil_node_complete_io(node, fil_system, OS_FILE_READ);
} }
return(space); return(space);
...@@ -6891,6 +6896,7 @@ Get id of first tablespace or ULINT_UNDEFINED if none */ ...@@ -6891,6 +6896,7 @@ Get id of first tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_first_space() fil_get_first_space()
/*=================*/
{ {
ulint out_id = ULINT_UNDEFINED; ulint out_id = ULINT_UNDEFINED;
fil_space_t* space; fil_space_t* space;
...@@ -6914,11 +6920,84 @@ fil_get_first_space() ...@@ -6914,11 +6920,84 @@ fil_get_first_space()
return out_id; return out_id;
} }
/******************************************************************
Get id of first tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_first_space_safe()
/*======================*/
{
ulint out_id = ULINT_UNDEFINED;
fil_space_t* space;
mutex_enter(&fil_system->mutex);
space = UT_LIST_GET_FIRST(fil_system->space_list);
if (space != NULL) {
do
{
if (!space->stop_new_ops && UT_LIST_GET_LEN(space->chain) > 0) {
out_id = space->id;
break;
}
space = UT_LIST_GET_NEXT(space_list, space);
} while (space != NULL);
}
mutex_exit(&fil_system->mutex);
return out_id;
}
/****************************************************************** /******************************************************************
Get id of next tablespace or ULINT_UNDEFINED if none */ Get id of next tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_next_space(ulint id) fil_get_next_space(
/*===============*/
ulint id) /*!< in: previous space id */
{
bool found;
fil_space_t* space;
ulint out_id = ULINT_UNDEFINED;
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(id);
if (space == NULL) {
/* we didn't find it...search for space with space->id > id */
found = false;
space = UT_LIST_GET_FIRST(fil_system->space_list);
} else {
/* we found it, take next available space */
found = true;
}
while ((space = UT_LIST_GET_NEXT(space_list, space)) != NULL) {
if (!found && space->id <= id)
continue;
if (!space->stop_new_ops && UT_LIST_GET_LEN(space->chain) > 0) {
/* inc reference to prevent drop */
out_id = space->id;
break;
}
}
mutex_exit(&fil_system->mutex);
return out_id;
}
/******************************************************************
Get id of next tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_next_space_safe(
/*====================*/
ulint id) /*!< in: previous space id */
{ {
bool found; bool found;
fil_space_t* space; fil_space_t* space;
...@@ -6958,7 +7037,7 @@ Get crypt data for a tablespace */ ...@@ -6958,7 +7037,7 @@ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
fil_space_crypt_t* fil_space_crypt_t*
fil_space_get_crypt_data( fil_space_get_crypt_data(
/*==================*/ /*=====================*/
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
{ {
fil_space_t* space; fil_space_t* space;
...@@ -6984,7 +7063,7 @@ Get crypt data for a tablespace */ ...@@ -6984,7 +7063,7 @@ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
fil_space_crypt_t* fil_space_crypt_t*
fil_space_set_crypt_data( fil_space_set_crypt_data(
/*==================*/ /*=====================*/
ulint id, /*!< in: space id */ ulint id, /*!< in: space id */
fil_space_crypt_t* crypt_data) /*!< in: crypt data */ fil_space_crypt_t* crypt_data) /*!< in: crypt data */
{ {
......
...@@ -1292,15 +1292,32 @@ Get id of first tablespace or ULINT_UNDEFINED if none */ ...@@ -1292,15 +1292,32 @@ Get id of first tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_first_space(); fil_get_first_space();
/*=================*/
/****************************************************************** /******************************************************************
Get id of next tablespace or ULINT_UNDEFINED if none */ Get id of next tablespace or ULINT_UNDEFINED if none */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_get_next_space( fil_get_next_space(
/*===============*/
ulint id); /*!< in: space id */ ulint id); /*!< in: space id */
#endif /******************************************************************
Get id of first tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_first_space_safe();
/*======================*/
/******************************************************************
Get id of next tablespace that has node or ULINT_UNDEFINED if none */
UNIV_INTERN
ulint
fil_get_next_space_safe(
/*====================*/
ulint id); /*!< in: previous space id */
#endif /* UNIV_INNOCHECKSUM */
/*******************************************************************//** /*******************************************************************//**
Return space flags */ Return space flags */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment