Browse Source

MENT-2235 Aria engine: log initialization failed

Some thing causes the aria_log_control file to be larger than the expected
52 bytes. The control file has the correct information but somehow it
is filled up with ox00 bytes up to 512 bytes.
This could have happened in case of a file system crash that enlarged
the file to the sector boundary.

Fixed that aria will ignore bytes outside of it's expected

Other things:
- Fixed wrong DBUG_ASSERT() in my_malloc_size_cb_func() that could cause
  crashes in debug binaries during Aria recovery.
bb-10.6-mdev-36221
Monty 7 months ago
parent
commit
b12e8d9095
  1. 10
      sql/mysqld.cc
  2. 45
      storage/maria/ma_control_file.c

10
sql/mysqld.cc

@ -3635,12 +3635,12 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific)
#endif
/*
When thread specific is set, both mysqld_server_initialized and thd
must be set, and we check that with DBUG_ASSERT.
However, do not crash, if current_thd is NULL, in release version.
is_thread_specific is only relevant when a THD exist and the server
has fully started. is_thread_specific can be set during recovery by
Aria for functions that are normally only run in one thread.
However InnoDB sets thd early, so we can use it.
*/
DBUG_ASSERT(!is_thread_specific || (mysqld_server_initialized && thd));
DBUG_ASSERT(!is_thread_specific || thd || !plugins_are_initialized);
if (is_thread_specific && likely(thd)) /* If thread specific memory */
{

45
storage/maria/ma_control_file.c

@ -275,7 +275,7 @@ CONTROL_FILE_ERROR ma_control_file_open(my_bool create_if_missing,
my_bool wait_for_lock)
{
uchar buffer[CF_MAX_SIZE];
char name[FN_REFLEN], errmsg_buff[256];
char name[FN_REFLEN], errmsg_buff[512];
const char *errmsg, *lock_failed_errmsg= "Could not get an exclusive lock;"
" file is probably in use by another process";
uint new_cf_create_time_size, new_cf_changeable_size, new_block_size;
@ -399,10 +399,14 @@ CONTROL_FILE_ERROR ma_control_file_open(my_bool create_if_missing,
if (new_cf_create_time_size < CF_MIN_CREATE_TIME_TOTAL_SIZE ||
new_cf_changeable_size < CF_MIN_CHANGEABLE_TOTAL_SIZE ||
new_cf_create_time_size + new_cf_changeable_size != file_size)
new_cf_create_time_size + new_cf_changeable_size > file_size)
{
error= CONTROL_FILE_INCONSISTENT_INFORMATION;
errmsg= "Sizes stored in control file are inconsistent";
sprintf(errmsg_buff,
"Sizes stored in control file are inconsistent. "
"create_time_size: %u changeable_size: %u file_size: %llu",
new_cf_create_time_size, new_cf_changeable_size, (ulonglong) file_size);
errmsg= errmsg_buff;
goto err;
}
@ -613,6 +617,20 @@ my_bool ma_control_file_inited(void)
return (control_file_fd >= 0);
}
static int check_zerofill(uchar *buffer, ulonglong offset, ulonglong length)
{
uchar *pos= buffer + offset, *end= buffer+length;
while (pos < end)
{
if (*pos++)
return 1;
}
return 0;
}
/**
Print content of aria_log_control file
*/
@ -620,6 +638,7 @@ my_bool ma_control_file_inited(void)
my_bool print_aria_log_control()
{
uchar buffer[CF_MAX_SIZE];
char errmsg_buff[512];
char name[FN_REFLEN], uuid_str[MY_UUID_STRING_LENGTH+1];
const char *errmsg;
uint new_cf_create_time_size, new_cf_changeable_size;
@ -696,10 +715,14 @@ my_bool print_aria_log_control()
if (new_cf_create_time_size < CF_MIN_CREATE_TIME_TOTAL_SIZE ||
new_cf_changeable_size < CF_MIN_CHANGEABLE_TOTAL_SIZE ||
new_cf_create_time_size + new_cf_changeable_size != file_size)
new_cf_create_time_size + new_cf_changeable_size > file_size)
{
error= CONTROL_FILE_INCONSISTENT_INFORMATION;
errmsg= "Sizes stored in control file are inconsistent";
sprintf(errmsg_buff,
"Sizes stored in control file are inconsistent. "
"create_time_size: %u changeable_size: %u file_size: %llu",
new_cf_create_time_size, new_cf_changeable_size, (ulonglong) file_size);
errmsg= errmsg_buff;
goto err;
}
checkpoint_lsn= lsn_korr(buffer + new_cf_create_time_size +
@ -723,6 +746,18 @@ my_bool print_aria_log_control()
(buffer + new_cf_create_time_size + CF_RECOV_FAIL_OFFSET)[0];
printf("recovery_failures: %u\n", recovery_fails);
}
if (check_zerofill(buffer, new_cf_create_time_size + new_cf_changeable_size, file_size))
{
printf("Warning: %s file_size is %llu (should be %llu) and contains unknown data.\n"
"It will still work but should be examined.\n",
name, (ulonglong) file_size,
(ulonglong) (new_cf_create_time_size + new_cf_changeable_size));
}
else if (new_cf_create_time_size + new_cf_changeable_size < file_size)
printf("Note: file_size (%llu) is bigger than the expected file size %llu.\n"
"This is unexpected but will not cause any issues.\n",
(ulonglong) file_size,
(ulonglong) (new_cf_create_time_size + new_cf_changeable_size));
mysql_file_close(file, MYF(0));
DBUG_RETURN(0);

Loading…
Cancel
Save