Commit 2f46e5b9 authored by Jan Lindström's avatar Jan Lindström

MDEV-6070: FusionIO: Failure to create a table with ATOMIC_WRITES

option leaves the database in inconsistent state,

Analysis: Problem was that atomic writes variable had incorrect
type on same places leading to fact that e.g. OFF option was
not regognized. Furthermore, some error check code was missing
from both InnoDB and XtraDB engines. Finally, when table is
created we have already created the .ibd file and if we can't
set atomic writes it stays there.

Fix: Fix atomic writes variable type to ulint as it should be.
Fix: Add proper error code checking on os errors on both InnoDB
and XtraDB
Fix: Remove the .idb file when atomic writes can't be enabled
to a new table.
parent 13c73c31
......@@ -745,7 +745,7 @@ fil_node_open_file(
ulint space_id;
ulint flags=0;
ulint page_size;
ibool atomic_writes=FALSE;
ulint atomic_writes=0;
ut_ad(mutex_own(&(system->mutex)));
ut_a(node->n_pending == 0);
......@@ -3425,7 +3425,7 @@ fil_create_new_single_table_tablespace(
/* TRUE if a table is created with CREATE TEMPORARY TABLE */
bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY);
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags);
bool atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
ut_a(space_id > 0);
ut_ad(!srv_read_only_mode);
......@@ -3720,7 +3720,7 @@ fil_open_single_table_tablespace(
fsp_open_info remote;
ulint tablespaces_found = 0;
ulint valid_tablespaces_found = 0;
ibool atomic_writes = FALSE;
ulint atomic_writes = 0;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!fix_dict || rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
......
......@@ -399,9 +399,8 @@ os_file_set_atomic_writes(
if (ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option)) {
fprintf(stderr, "InnoDB: Error: trying to enable atomic writes on "
"file %s on non-supported platform! Please restart with "
"innodb_use_atomic_writes disabled.\n", name);
fprintf(stderr, "InnoDB: Warning:Trying to enable atomic writes on "
"file %s on non-supported platform!\n", name);
os_file_handle_error_no_exit(name, "ioctl", FALSE, __FILE__, __LINE__);
return(FALSE);
}
......@@ -409,8 +408,7 @@ os_file_set_atomic_writes(
return(TRUE);
#else
fprintf(stderr, "InnoDB: Error: trying to enable atomic writes on "
"non-supported platform! Please restart with "
"innodb_use_atomic_writes disabled.\n");
"file %s on non-supported platform!\n", name);
return(FALSE);
#endif
}
......@@ -561,6 +559,19 @@ os_file_get_last_error_low(
"InnoDB: because of either a thread exit"
" or an application request.\n"
"InnoDB: Retry attempt is made.\n");
} else if (err == ECANCELED || err == ENOTTY) {
if (strerror(err) != NULL) {
fprintf(stderr,
"InnoDB: Error number %d"
" means '%s'.\n",
err, strerror(err));
}
if(srv_use_atomic_writes) {
fprintf(stderr,
"InnoDB: Error trying to enable atomic writes on "
"non-supported destination!\n");
}
} else {
fprintf(stderr,
"InnoDB: Some operating system error numbers"
......@@ -620,11 +631,14 @@ os_file_get_last_error_low(
fprintf(stderr,
"InnoDB: The error means mysqld does not have"
" the access rights to\n"
"InnoDECANCELEDB: the directory.\n");
} else if (err == ECANCELED) {
"InnoDB: the directory.\n");
} else if (err == ECANCELED || err == ENOTTY) {
if (strerror(err) != NULL) {
fprintf(stderr,
"InnoDB: Operation canceled (%d):%s\n",
"InnoDB: Error number %d"
" means '%s'.\n",
err, strerror(err));
}
if(srv_use_atomic_writes) {
fprintf(stderr,
......@@ -663,6 +677,7 @@ os_file_get_last_error_low(
case EISDIR:
return(OS_FILE_PATH_ERROR);
case ECANCELED:
case ENOTTY:
return(OS_FILE_OPERATION_NOT_SUPPORTED);
case EAGAIN:
if (srv_use_native_aio) {
......@@ -1521,14 +1536,22 @@ os_file_create_simple_no_error_handling_func(
attributes,
NULL); // No template file
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != INVALID_HANDLE_VALUE
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
CloseHandle(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = INVALID_HANDLE_VALUE;
}
}
*success = (file != INVALID_HANDLE_VALUE);
#else /* __WIN__ */
......@@ -1590,14 +1613,22 @@ os_file_create_simple_no_error_handling_func(
}
#endif /* USE_FILE_LOCK */
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != -1
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
*success = FALSE;
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
close(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = -1;
}
}
#endif /* __WIN__ */
......@@ -1836,14 +1867,22 @@ os_file_create_func(
} while (retry);
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != INVALID_HANDLE_VALUE
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
CloseHandle(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = INVALID_HANDLE_VALUE;
}
}
#else /* __WIN__ */
int create_flag;
const char* mode_str = NULL;
......@@ -1972,14 +2011,22 @@ os_file_create_func(
}
#endif /* USE_FILE_LOCK */
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != -1
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
*success = FALSE;
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
close(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = -1;
}
}
#endif /* __WIN__ */
return(file);
......
......@@ -746,7 +746,7 @@ fil_node_open_file(
ulint space_id;
ulint flags=0;
ulint page_size;
ibool atomic_writes=FALSE;
ulint atomic_writes=0;
ut_ad(mutex_own(&(system->mutex)));
ut_a(node->n_pending == 0);
......@@ -3288,6 +3288,8 @@ fil_create_link_file(
} else if (error == OS_FILE_DISK_FULL) {
err = DB_OUT_OF_FILE_SPACE;
} else if (error == OS_FILE_OPERATION_NOT_SUPPORTED) {
err = DB_UNSUPPORTED;
} else {
err = DB_ERROR;
}
......@@ -3448,7 +3450,7 @@ fil_create_new_single_table_tablespace(
/* TRUE if a table is created with CREATE TEMPORARY TABLE */
bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY);
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags);
bool atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags);
ut_a(space_id > 0);
ut_ad(!srv_read_only_mode);
......@@ -3509,6 +3511,11 @@ fil_create_new_single_table_tablespace(
goto error_exit_3;
}
if (error == OS_FILE_OPERATION_NOT_SUPPORTED) {
err = DB_UNSUPPORTED;
goto error_exit_3;
}
if (error == OS_FILE_DISK_FULL) {
err = DB_OUT_OF_FILE_SPACE;
goto error_exit_3;
......@@ -3735,7 +3742,7 @@ fil_open_single_table_tablespace(
fsp_open_info remote;
ulint tablespaces_found = 0;
ulint valid_tablespaces_found = 0;
ibool atomic_writes = FALSE;
ulint atomic_writes = 0;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!fix_dict || rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
......@@ -3746,6 +3753,8 @@ fil_open_single_table_tablespace(
return(DB_CORRUPTION);
}
atomic_writes = fsp_flags_get_atomic_writes(flags);
/* If the tablespace was relocated, we do not
compare the DATA_DIR flag */
ulint mod_flags = flags & ~FSP_FLAGS_MASK_DATA_DIR;
......
......@@ -628,10 +628,13 @@ os_file_get_last_error_low(
"InnoDB: because of either a thread exit"
" or an application request.\n"
"InnoDB: Retry attempt is made.\n");
} else if (err == ECANCELED) {
} else if (err == ECANCELED || err == ENOTTY) {
if (strerror(err) != NULL) {
fprintf(stderr,
"InnoDB: Operation canceled (%d):%s\n",
"InnoDB: Error number %d"
" means '%s'.\n",
err, strerror(err));
}
if(srv_use_atomic_writes) {
fprintf(stderr,
......@@ -698,6 +701,20 @@ os_file_get_last_error_low(
"InnoDB: The error means mysqld does not have"
" the access rights to\n"
"InnoDB: the directory.\n");
} else if (err == ECANCELED || err == ENOTTY) {
if (strerror(err) != NULL) {
fprintf(stderr,
"InnoDB: Error number %d"
" means '%s'.\n",
err, strerror(err));
}
if(srv_use_atomic_writes) {
fprintf(stderr,
"InnoDB: Error trying to enable atomic writes on "
"non-supported destination!\n");
}
} else {
if (strerror(err) != NULL) {
fprintf(stderr,
......@@ -735,6 +752,7 @@ os_file_get_last_error_low(
}
break;
case ECANCELED:
case ENOTTY:
return(OS_FILE_OPERATION_NOT_SUPPORTED);
case EINTR:
if (srv_use_native_aio) {
......@@ -1591,14 +1609,22 @@ os_file_create_simple_no_error_handling_func(
attributes,
NULL); // No template file
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != INVALID_HANDLE_VALUE
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
CloseHandle(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = INVALID_HANDLE_VALUE;
}
}
*success = (file != INVALID_HANDLE_VALUE);
#else /* __WIN__ */
......@@ -1660,14 +1686,22 @@ os_file_create_simple_no_error_handling_func(
}
#endif /* USE_FILE_LOCK */
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != -1
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
*success = FALSE;
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
close(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = -1;
}
}
#endif /* __WIN__ */
......@@ -1752,15 +1786,16 @@ os_file_set_atomic_writes(
if (ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option)) {
fprintf(stderr, "InnoDB: Warning:Trying to enable atomic writes on "
"file %s on non-supported platform!\n", name);
os_file_handle_error_no_exit(name, "ioctl(DFS_IOCTL_ATOMIC_WRITE_SET)", FALSE, __FILE__, __LINE__);
return(FALSE);
}
return(TRUE);
#else
ib_logf(IB_LOG_LEVEL_ERROR,
"trying to enable atomic writes on non-supported platform! "
"Please restart with innodb_use_atomic_writes disabled.\n");
fprintf(stderr, "InnoDB: Error: trying to enable atomic writes on "
"file %s on non-supported platform!\n", name);
return(FALSE);
#endif
}
......@@ -1951,14 +1986,22 @@ os_file_create_func(
} while (retry);
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != INVALID_HANDLE_VALUE
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
CloseHandle(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = INVALID_HANDLE_VALUE;
}
}
#else /* __WIN__ */
int create_flag;
......@@ -2090,14 +2133,22 @@ os_file_create_func(
}
#endif /* USE_FILE_LOCK */
/* If we have proper file handle and atomic writes should be used,
try to set atomic writes and if that fails when creating a new
table, produce a error. If atomic writes are used on existing
file, ignore error and use traditional writes for that file */
if (file != -1
&& (awrites == ATOMIC_WRITES_ON ||
(srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT))
&& !os_file_set_atomic_writes(name, file)) {
*success = FALSE;
if (create_mode == OS_FILE_CREATE) {
fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n");
close(file);
os_file_delete_if_exists_func(name);
*success = FALSE;
file = -1;
}
}
#endif /* __WIN__ */
......
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