mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
e223c32077
The patch for Bug 26379 (Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table) fixed this bug too. However it revealed a new bug that crashed the server. Flushing a merge table at the moment when it is between open and attach of children crashed the server. The flushing thread wants to abort locks on the flushed table. It calls ha_myisammrg::lock_count() and ha_myisammrg::store_lock() on the TABLE object of the other thread. Changed ha_myisammrg::lock_count() and ha_myisammrg::store_lock() to accept non-attached children. ha_myisammrg::lock_count() returns the number of MyISAM tables in the MERGE table so that the memory allocation done by get_lock_data() is done correctly, even if the children become attached before ha_myisammrg::store_lock() is called. ha_myisammrg::store_lock() will not return any lock if the children are not attached. This is however a change in the handler interface. lock_count() can now return a higher number than store_lock() stores locks. This is more safe than the reverse implementation would be. get_lock_data() in the SQL layer is adjusted accordingly. It sets MYSQL_LOCK::lock_count based on the number of locks returned by the handler::store_lock() calls, not based on the numbers returned by the handler::lock_count() calls. The latter are only used for allocation of memory now. No test case. The test suite cannot reliably run FLUSH between lock_count() and store_lock() of another thread. The bug report contains a program that can repeat the problem with some probability. include/myisammrg.h: Bug#30273 - merge tables: Can't lock file (errno: 155) Added mutex to struct st_myrg_info (MYRG_INFO). sql/handler.h: Bug#30273 - merge tables: Can't lock file (errno: 155) Extended comments for handler::lock_count() and handler::store_lock(). sql/lock.cc: Bug#30273 - merge tables: Can't lock file (errno: 155) Changed get_lock_data() so that the final lock_count is taken from the number of locks returned from handler::store_lock() instead of from handler::lock_count(). sql/sql_base.cc: Fixed a purecov comment. (unrelated to the rest of the changeset) storage/myisammrg/ha_myisammrg.cc: Bug#30273 - merge tables: Can't lock file (errno: 155) Changed ha_myisammrg::lock_count() and ha_myisammrg::store_lock() to accept non-attached children. Protected ha_myisammrg::store_lock() by MYRG_INFO::mutex. storage/myisammrg/myrg_close.c: Bug#30273 - merge tables: Can't lock file (errno: 155) Added MYRG_INFO::mutex destruction to myrg_parent_close(). storage/myisammrg/myrg_open.c: Bug#30273 - merge tables: Can't lock file (errno: 155) Added MYRG_INFO::mutex initialization to myrg_parent_open(). Protected myrg_attach_children() and myrg_detach_children() by MYRG_INFO::mutex. Fixed a purecov comment. (unrelated to the rest of the changeset)
68 lines
2.4 KiB
C
68 lines
2.4 KiB
C
/* Copyright (C) 2000-2001 MySQL AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
/* close a isam-database */
|
|
|
|
#include "myrg_def.h"
|
|
|
|
int myrg_close(MYRG_INFO *info)
|
|
{
|
|
int error=0,new_error;
|
|
MYRG_TABLE *file;
|
|
DBUG_ENTER("myrg_close");
|
|
|
|
/*
|
|
Assume that info->children_attached means that this is called from
|
|
direct use of MERGE, not from a MySQL server. In this case the
|
|
children must be closed and info->rec_per_key_part is part of the
|
|
'info' multi_alloc.
|
|
If info->children_attached is false, this is called from a MySQL
|
|
server. Children are closed independently but info->rec_per_key_part
|
|
must be freed.
|
|
Just in case of a server panic (myrg_panic()) info->children_attached
|
|
might be true. We would close the children though they should be
|
|
closed independently and info->rec_per_key_part is not freed.
|
|
This should be acceptable for a panic.
|
|
In case of a MySQL server and no children, children_attached is
|
|
always true. In this case no rec_per_key_part has been allocated.
|
|
So it is correct to use the branch where an empty list of tables is
|
|
(not) closed.
|
|
*/
|
|
if (info->children_attached)
|
|
{
|
|
for (file= info->open_tables; file != info->end_table; file++)
|
|
{
|
|
/* purecov: begin inspected */
|
|
if ((new_error= mi_close(file->table)))
|
|
error= new_error;
|
|
else
|
|
file->table= NULL;
|
|
/* purecov: end */
|
|
}
|
|
}
|
|
else
|
|
my_free((uchar*) info->rec_per_key_part, MYF(MY_ALLOW_ZERO_PTR));
|
|
delete_queue(&info->by_key);
|
|
pthread_mutex_lock(&THR_LOCK_open);
|
|
myrg_open_list=list_delete(myrg_open_list,&info->open_list);
|
|
pthread_mutex_unlock(&THR_LOCK_open);
|
|
VOID(pthread_mutex_destroy(&info->mutex));
|
|
my_free((uchar*) info,MYF(0));
|
|
if (error)
|
|
{
|
|
DBUG_RETURN(my_errno=error);
|
|
}
|
|
DBUG_RETURN(0);
|
|
}
|