mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES DIRECTLY
FROM BUFFER POOL rb://975 approved by: Marko Makela There is a race in lock_validate() where we try to access a page without ensuring that the tablespace stays valid during the operation i.e.: it is not deleted. This patch tries to fix that by using an existing flag (the flag is renamed to make it's name more generic in line with it's new use).
This commit is contained in:
parent
04c96834cc
commit
0023147055
5 changed files with 58 additions and 43 deletions
|
|
@ -1,3 +1,10 @@
|
||||||
|
2012-03-15 The InnoDB Team
|
||||||
|
|
||||||
|
* fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/fil0fil.h,
|
||||||
|
lock/lock0lock.c:
|
||||||
|
Fix Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES
|
||||||
|
DIRECTLY FROM BUFFER POOL
|
||||||
|
|
||||||
2012-03-15 The InnoDB Team
|
2012-03-15 The InnoDB Team
|
||||||
|
|
||||||
* handler/ha_innodb.cc:
|
* handler/ha_innodb.cc:
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ struct fil_space_struct {
|
||||||
.ibd file of tablespace and want to
|
.ibd file of tablespace and want to
|
||||||
stop temporarily posting of new i/o
|
stop temporarily posting of new i/o
|
||||||
requests on the file */
|
requests on the file */
|
||||||
ibool stop_ibuf_merges;
|
ibool stop_new_ops;
|
||||||
/*!< we set this TRUE when we start
|
/*!< we set this TRUE when we start
|
||||||
deleting a single-table tablespace */
|
deleting a single-table tablespace */
|
||||||
ibool is_being_deleted;
|
ibool is_being_deleted;
|
||||||
|
|
@ -200,12 +200,13 @@ struct fil_space_struct {
|
||||||
ulint n_pending_flushes; /*!< this is positive when flushing
|
ulint n_pending_flushes; /*!< this is positive when flushing
|
||||||
the tablespace to disk; dropping of the
|
the tablespace to disk; dropping of the
|
||||||
tablespace is forbidden if this is positive */
|
tablespace is forbidden if this is positive */
|
||||||
ulint n_pending_ibuf_merges;/*!< this is positive
|
ulint n_pending_ops;/*!< this is positive when we
|
||||||
when merging insert buffer entries to
|
have pending operations against this
|
||||||
a page so that we may need to access
|
tablespace. The pending operations can
|
||||||
the ibuf bitmap page in the
|
be ibuf merges or lock validation code
|
||||||
tablespade: dropping of the tablespace
|
trying to read a block.
|
||||||
is forbidden if this is positive */
|
Dropping of the tablespace is forbidden
|
||||||
|
if this is positive */
|
||||||
hash_node_t hash; /*!< hash chain node */
|
hash_node_t hash; /*!< hash chain node */
|
||||||
hash_node_t name_hash;/*!< hash chain the name_hash table */
|
hash_node_t name_hash;/*!< hash chain the name_hash table */
|
||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
|
|
@ -1236,7 +1237,7 @@ try_again:
|
||||||
}
|
}
|
||||||
|
|
||||||
space->stop_ios = FALSE;
|
space->stop_ios = FALSE;
|
||||||
space->stop_ibuf_merges = FALSE;
|
space->stop_new_ops = FALSE;
|
||||||
space->is_being_deleted = FALSE;
|
space->is_being_deleted = FALSE;
|
||||||
space->purpose = purpose;
|
space->purpose = purpose;
|
||||||
space->size = 0;
|
space->size = 0;
|
||||||
|
|
@ -1245,7 +1246,7 @@ try_again:
|
||||||
space->n_reserved_extents = 0;
|
space->n_reserved_extents = 0;
|
||||||
|
|
||||||
space->n_pending_flushes = 0;
|
space->n_pending_flushes = 0;
|
||||||
space->n_pending_ibuf_merges = 0;
|
space->n_pending_ops = 0;
|
||||||
|
|
||||||
UT_LIST_INIT(space->chain);
|
UT_LIST_INIT(space->chain);
|
||||||
space->magic_n = FIL_SPACE_MAGIC_N;
|
space->magic_n = FIL_SPACE_MAGIC_N;
|
||||||
|
|
@ -1836,13 +1837,12 @@ fil_read_flushed_lsn_and_arch_log_no(
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Increments the count of pending insert buffer page merges, if space is not
|
Increments the count of pending operation, if space is not being deleted.
|
||||||
being deleted.
|
@return TRUE if being deleted, and operation should be skipped */
|
||||||
@return TRUE if being deleted, and ibuf merges should be skipped */
|
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ibool
|
ibool
|
||||||
fil_inc_pending_ibuf_merges(
|
fil_inc_pending_ops(
|
||||||
/*========================*/
|
/*================*/
|
||||||
ulint id) /*!< in: space id */
|
ulint id) /*!< in: space id */
|
||||||
{
|
{
|
||||||
fil_space_t* space;
|
fil_space_t* space;
|
||||||
|
|
@ -1858,13 +1858,13 @@ fil_inc_pending_ibuf_merges(
|
||||||
(ulong) id);
|
(ulong) id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space == NULL || space->stop_ibuf_merges) {
|
if (space == NULL || space->stop_new_ops) {
|
||||||
mutex_exit(&fil_system->mutex);
|
mutex_exit(&fil_system->mutex);
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
space->n_pending_ibuf_merges++;
|
space->n_pending_ops++;
|
||||||
|
|
||||||
mutex_exit(&fil_system->mutex);
|
mutex_exit(&fil_system->mutex);
|
||||||
|
|
||||||
|
|
@ -1872,11 +1872,11 @@ fil_inc_pending_ibuf_merges(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Decrements the count of pending insert buffer page merges. */
|
Decrements the count of pending operations. */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
void
|
void
|
||||||
fil_decr_pending_ibuf_merges(
|
fil_decr_pending_ops(
|
||||||
/*=========================*/
|
/*=================*/
|
||||||
ulint id) /*!< in: space id */
|
ulint id) /*!< in: space id */
|
||||||
{
|
{
|
||||||
fil_space_t* space;
|
fil_space_t* space;
|
||||||
|
|
@ -1887,13 +1887,13 @@ fil_decr_pending_ibuf_merges(
|
||||||
|
|
||||||
if (space == NULL) {
|
if (space == NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Error: decrementing ibuf merge of a"
|
"InnoDB: Error: decrementing pending operation"
|
||||||
" dropped tablespace %lu\n",
|
" of a dropped tablespace %lu\n",
|
||||||
(ulong) id);
|
(ulong) id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space != NULL) {
|
if (space != NULL) {
|
||||||
space->n_pending_ibuf_merges--;
|
space->n_pending_ops--;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&fil_system->mutex);
|
mutex_exit(&fil_system->mutex);
|
||||||
|
|
@ -2183,15 +2183,15 @@ fil_delete_tablespace(
|
||||||
char* path;
|
char* path;
|
||||||
|
|
||||||
ut_a(id != 0);
|
ut_a(id != 0);
|
||||||
stop_ibuf_merges:
|
stop_new_ops:
|
||||||
mutex_enter(&fil_system->mutex);
|
mutex_enter(&fil_system->mutex);
|
||||||
|
|
||||||
space = fil_space_get_by_id(id);
|
space = fil_space_get_by_id(id);
|
||||||
|
|
||||||
if (space != NULL) {
|
if (space != NULL) {
|
||||||
space->stop_ibuf_merges = TRUE;
|
space->stop_new_ops = TRUE;
|
||||||
|
|
||||||
if (space->n_pending_ibuf_merges == 0) {
|
if (space->n_pending_ops == 0) {
|
||||||
mutex_exit(&fil_system->mutex);
|
mutex_exit(&fil_system->mutex);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
@ -2205,9 +2205,10 @@ stop_ibuf_merges:
|
||||||
ut_print_filename(stderr, space->name);
|
ut_print_filename(stderr, space->name);
|
||||||
fprintf(stderr, ",\n"
|
fprintf(stderr, ",\n"
|
||||||
"InnoDB: but there are %lu pending"
|
"InnoDB: but there are %lu pending"
|
||||||
" ibuf merges on it.\n"
|
" operations (most likely ibuf merges)"
|
||||||
|
" on it.\n"
|
||||||
"InnoDB: Loop %lu.\n",
|
"InnoDB: Loop %lu.\n",
|
||||||
(ulong) space->n_pending_ibuf_merges,
|
(ulong) space->n_pending_ops,
|
||||||
(ulong) count);
|
(ulong) count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2216,7 +2217,7 @@ stop_ibuf_merges:
|
||||||
os_thread_sleep(20000);
|
os_thread_sleep(20000);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
goto stop_ibuf_merges;
|
goto stop_new_ops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2242,7 +2243,7 @@ try_again:
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(space);
|
ut_a(space);
|
||||||
ut_a(space->n_pending_ibuf_merges == 0);
|
ut_a(space->n_pending_ops == 0);
|
||||||
|
|
||||||
space->is_being_deleted = TRUE;
|
space->is_being_deleted = TRUE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3281,7 +3281,7 @@ ibuf_merge_or_delete_for_page(
|
||||||
function. When the counter is > 0, that prevents tablespace
|
function. When the counter is > 0, that prevents tablespace
|
||||||
from being dropped. */
|
from being dropped. */
|
||||||
|
|
||||||
tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
|
tablespace_being_deleted = fil_inc_pending_ops(space);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
|
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
|
||||||
/* Do not try to read the bitmap page from space;
|
/* Do not try to read the bitmap page from space;
|
||||||
|
|
@ -3305,7 +3305,7 @@ ibuf_merge_or_delete_for_page(
|
||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
|
|
||||||
if (!tablespace_being_deleted) {
|
if (!tablespace_being_deleted) {
|
||||||
fil_decr_pending_ibuf_merges(space);
|
fil_decr_pending_ops(space);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -3537,7 +3537,7 @@ reset_bit:
|
||||||
|
|
||||||
if (update_ibuf_bitmap && !tablespace_being_deleted) {
|
if (update_ibuf_bitmap && !tablespace_being_deleted) {
|
||||||
|
|
||||||
fil_decr_pending_ibuf_merges(space);
|
fil_decr_pending_ops(space);
|
||||||
}
|
}
|
||||||
|
|
||||||
ibuf_exit();
|
ibuf_exit();
|
||||||
|
|
|
||||||
|
|
@ -340,20 +340,19 @@ fil_read_flushed_lsn_and_arch_log_no(
|
||||||
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
|
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
|
||||||
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
|
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Increments the count of pending insert buffer page merges, if space is not
|
Increments the count of pending operation, if space is not being deleted.
|
||||||
being deleted.
|
@return TRUE if being deleted, and operation should be skipped */
|
||||||
@return TRUE if being deleted, and ibuf merges should be skipped */
|
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ibool
|
ibool
|
||||||
fil_inc_pending_ibuf_merges(
|
fil_inc_pending_ops(
|
||||||
/*========================*/
|
/*================*/
|
||||||
ulint id); /*!< in: space id */
|
ulint id); /*!< in: space id */
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Decrements the count of pending insert buffer page merges. */
|
Decrements the count of pending operations. */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
void
|
void
|
||||||
fil_decr_pending_ibuf_merges(
|
fil_decr_pending_ops(
|
||||||
/*=========================*/
|
/*=================*/
|
||||||
ulint id); /*!< in: space id */
|
ulint id); /*!< in: space id */
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
|
|
|
||||||
|
|
@ -5040,9 +5040,17 @@ lock_validate(void)
|
||||||
|
|
||||||
lock_mutex_exit_kernel();
|
lock_mutex_exit_kernel();
|
||||||
|
|
||||||
lock_rec_validate_page(space,
|
/* Make sure that the tablespace is not
|
||||||
fil_space_get_zip_size(space),
|
deleted while we are trying to access
|
||||||
page_no);
|
the page. */
|
||||||
|
if (!fil_inc_pending_ops(space)) {
|
||||||
|
lock_rec_validate_page(
|
||||||
|
space,
|
||||||
|
fil_space_get_zip_size(space),
|
||||||
|
page_no);
|
||||||
|
|
||||||
|
fil_decr_pending_ops(space);
|
||||||
|
}
|
||||||
|
|
||||||
lock_mutex_enter_kernel();
|
lock_mutex_enter_kernel();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue