[Commits] 5534d81: Merged following change from MySQL 5.6 to MariaDB 10.1 XtraDB

Jan Lindström jan.lindstrom at mariadb.com
Fri May 6 13:59:51 EEST 2016


revision-id: 5534d8143004022a8431068b1e1f53bd8d7046e9 (mariadb-10.1.13-41-g5534d81)
parent(s): 1512078a7a56779d6fdd307a93187b61494de897
committer: Jan Lindström
timestamp: 2016-05-06 13:56:25 +0300
message:

Merged following change from MySQL 5.6 to MariaDB 10.1 XtraDB
including the test case:

https://github.com/mysql/mysql-server/commit/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 at oracle.com>
Reviewed-by: Shaohua Wang <shaohua.wang at oracle.com>
RB: 11387

---
 .../suite/innodb/r/create_isl_with_direct.result   | 10 ++++++
 .../suite/innodb/t/create_isl_with_direct.opt      |  1 +
 .../suite/innodb/t/create_isl_with_direct.test     | 28 +++++++++++++++
 storage/xtradb/fil/fil0fil.cc                      | 40 +++++++++++++---------
 4 files changed, 63 insertions(+), 16 deletions(-)

diff --git a/mysql-test/suite/innodb/r/create_isl_with_direct.result b/mysql-test/suite/innodb/r/create_isl_with_direct.result
new file mode 100644
index 0000000..87544e6
--- /dev/null
+++ b/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;
diff --git a/mysql-test/suite/innodb/t/create_isl_with_direct.opt b/mysql-test/suite/innodb/t/create_isl_with_direct.opt
new file mode 100644
index 0000000..8f80f02
--- /dev/null
+++ b/mysql-test/suite/innodb/t/create_isl_with_direct.opt
@@ -0,0 +1 @@
+--innodb_flush_method=O_DIRECT
diff --git a/mysql-test/suite/innodb/t/create_isl_with_direct.test b/mysql-test/suite/innodb/t/create_isl_with_direct.test
new file mode 100644
index 0000000..34ea9c7
--- /dev/null
+++ b/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;
+ 
\ No newline at end of file
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index e77c97e..9fad342 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -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);
@@ -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);
@@ -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 {
@@ -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);
 


More information about the commits mailing list