Skip to content

Commit

Permalink
Merged following change from MySQL 5.6 to MariaDB 10.1 XtraDB
Browse files Browse the repository at this point in the history
including the test case:

mysql/mysql-server@520aedfe
INNODB: "DATA DIRECTORY" OPTION OF CREATE TABLE FAILS WITH PWRITE() OS
ERROR 22
Fix for version mysql-5.6
PROBLEM
========
For version mysql-5.6.27 onwards InnoDB fails to create a table
with explicit 'data directory' option when Innodb_flush_method
is set to O_DIRECT.While creating link file we get a  a pwrite
error 22 due to the alignment restrictions imposed by O_DIRECT
flag  which is being set for the link file created.

FIX
===
Fixed the above issue by making use of file IO functions while
creating the link file that wouldn't let the O_DIRECT flag
restrictions arise.

Reviewed-by: Kevin Lewis <kevin.lewis@oracle.com>
Reviewed-by: Shaohua Wang <shaohua.wang@oracle.com>
RB: 11387
  • Loading branch information
Jan Lindström committed May 6, 2016
1 parent 1512078 commit 5534d81
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 16 deletions.
10 changes: 10 additions & 0 deletions mysql-test/suite/innodb/r/create_isl_with_direct.result
@@ -0,0 +1,10 @@
SHOW VARIABLES LIKE 'innodb_flush_method';
Variable_name Value
innodb_flush_method O_DIRECT
CREATE TABLE t1 (x INT) ENGINE=INNODB, DATA DIRECTORY='MYSQL_TMP_DIR';
# Contents of tmp/test directory containing .ibd file
t1.ibd
# Contents of the 'test' database directory containing .isl and .frm files
t1.frm
t1.isl
DROP TABLE t1;
1 change: 1 addition & 0 deletions mysql-test/suite/innodb/t/create_isl_with_direct.opt
@@ -0,0 +1 @@
--innodb_flush_method=O_DIRECT
28 changes: 28 additions & 0 deletions mysql-test/suite/innodb/t/create_isl_with_direct.test
@@ -0,0 +1,28 @@
--source include/not_embedded.inc
--source include/have_innodb.inc
--source include/not_windows.inc

--disable_query_log
CALL mtr.add_suppression("\\[Warning\\] InnoDB: Failed to set O_DIRECT on file ./ibdata1: OPEN: Invalid argument, continuing anyway. O_DIRECT is known to result in 'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662.");

# The below mtr suppression to avoid failure in solaris platform.
CALL mtr.add_suppression("\\[ERROR\\] InnoDB: Failed to set DIRECTIO_ON on file.*");
--enable_query_log

SHOW VARIABLES LIKE 'innodb_flush_method';

let MYSQLD_DATADIR=`SELECT @@datadir`;

--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR

# Create a table with explicit data directory option.
EVAL CREATE TABLE t1 (x INT) ENGINE=INNODB, DATA DIRECTORY='$MYSQL_TMP_DIR';

--echo # Contents of tmp/test directory containing .ibd file
--list_files $MYSQL_TMP_DIR/test

--echo # Contents of the 'test' database directory containing .isl and .frm files
--list_files $MYSQLD_DATADIR/test

DROP TABLE t1;

40 changes: 24 additions & 16 deletions storage/xtradb/fil/fil0fil.cc
Expand Up @@ -3225,8 +3225,6 @@ fil_create_link_file(
const char* tablename, /*!< in: tablename */
const char* filepath) /*!< in: pathname of tablespace */
{
os_file_t file;
ibool success;
dberr_t err = DB_SUCCESS;
char* link_filepath;
char* prev_filepath = fil_read_link_file(tablename);
Expand All @@ -3245,16 +3243,24 @@ fil_create_link_file(

link_filepath = fil_make_isl_name(tablename);

/* Note that OS_FILE_READ_WRITE_CACHED used here to avoid
unnecessary errors on O_DIRECT, link files are not really
a data files. */
file = os_file_create_simple_no_error_handling(
innodb_file_data_key, link_filepath,
OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0);
/** Check if the file already exists. */
FILE* file = NULL;
ibool exists;
os_file_type_t ftype;

if (!success) {
/* The following call will print an error message */
ulint error = os_file_get_last_error(true);
bool success = os_file_status(link_filepath, &exists, &ftype);

ulint error = 0;
if (success && !exists) {
file = fopen(link_filepath, "w");
if (file == NULL) {
/* This call will print its own error message */
error = os_file_get_last_error(true);
}
} else {
error = OS_FILE_ALREADY_EXISTS;
}
if (error != 0) {

ut_print_timestamp(stderr);
fputs(" InnoDB: Cannot create file ", stderr);
Expand All @@ -3266,10 +3272,8 @@ fil_create_link_file(
ut_print_filename(stderr, filepath);
fputs(" already exists.\n", stderr);
err = DB_TABLESPACE_EXISTS;

} 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 {
Expand All @@ -3281,13 +3285,17 @@ fil_create_link_file(
return(err);
}

if (!os_file_write(link_filepath, file, filepath, 0,
strlen(filepath))) {
ulint rbytes = fwrite(filepath, 1, strlen(filepath), file);
if (rbytes != strlen(filepath)) {
os_file_get_last_error(true);
ib_logf(IB_LOG_LEVEL_ERROR,
"cannot write link file "
"%s",filepath);
err = DB_ERROR;
}

/* Close the file, we only need it at startup */
os_file_close(file);
fclose(file);

mem_free(link_filepath);

Expand Down

0 comments on commit 5534d81

Please sign in to comment.