Skip to content

Commit

Permalink
MDEV-9678: Data Directory bug
Browse files Browse the repository at this point in the history
    Problem was that link file (.isl) is also opened using O_DIRECT
    mode and if this fails the whole create table fails on internal
    error.

    Fixed by not using O_DIRECT on link files as they are used only
    on create table and startup and do not contain real data.
    O_DIRECT failures are successfully ignored for data files
    if O_DIRECT is not supported by file system on used
    data directory.
  • Loading branch information
Jan Lindström committed Mar 22, 2016
1 parent 37f915c commit f71c45c
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 35 deletions.
8 changes: 5 additions & 3 deletions storage/innobase/fil/fil0fil.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates.
Copyright (c) 2013, 2015, MariaDB Corporation.
Copyright (c) 2013, 2016, MariaDB Corporation.
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
Expand Down Expand Up @@ -3207,10 +3207,12 @@ 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, &success, 0);
OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0);

if (!success) {
/* The following call will print an error message */
Expand Down
7 changes: 5 additions & 2 deletions storage/innobase/include/os0file.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ enum os_file_create_t {
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */

#define OS_FILE_READ_WRITE_CACHED 666 /* OS_FILE_READ_WRITE but never
O_DIRECT. Only for
os_file_create_simple_no_error_handling
currently. */
/* Options for file_create */
#define OS_FILE_AIO 61
#define OS_FILE_NORMAL 62
Expand Down Expand Up @@ -542,7 +545,7 @@ UNIV_INTERN
void
os_file_set_nocache(
/*================*/
int fd, /*!< in: file descriptor to alter */
os_file_t fd, /*!< in: file descriptor to alter */
const char* file_name, /*!< in: file name, used in the
diagnostic message */
const char* operation_name);/*!< in: "open" or "create"; used in the
Expand Down
62 changes: 42 additions & 20 deletions storage/innobase/os/os0file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
Copyright (c) 2013, 2016, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
Expand Down Expand Up @@ -1350,7 +1350,8 @@ os_file_create_simple_func(

access = GENERIC_READ;

} else if (access_type == OS_FILE_READ_WRITE) {
} else if (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED) {
access = GENERIC_READ | GENERIC_WRITE;
} else {
ib_logf(IB_LOG_LEVEL_ERROR,
Expand Down Expand Up @@ -1454,7 +1455,8 @@ os_file_create_simple_func(
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
&& access_type == OS_FILE_READ_WRITE
&& (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED)
&& os_file_lock(file, name)) {

*success = FALSE;
Expand All @@ -1468,6 +1470,31 @@ os_file_create_simple_func(
return(file);
}

/** Disable OS I/O caching on the file if the file type and server
configuration requires it.
@param file handle to the file
@param name name of the file, for diagnostics
@param mode_str operation on the file, for diagnostics
@param type OS_LOG_FILE or OS_DATA_FILE
@param access_type if OS_FILE_READ_WRITE_CACHED, then caching will be disabled
unconditionally, ignored otherwise */
static
void
os_file_set_nocache_if_needed(os_file_t file, const char* name,
const char *mode_str, ulint type,
ulint access_type)
{
if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) {
return;
}

if (type == OS_DATA_FILE
&& (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
|| (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC))) {
os_file_set_nocache(file, name, mode_str);
}
}

/****************************************************************//**
NOTE! Use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
Expand Down Expand Up @@ -1523,7 +1550,8 @@ os_file_create_simple_no_error_handling_func(
access = GENERIC_READ;
} else if (srv_read_only_mode) {
access = GENERIC_READ;
} else if (access_type == OS_FILE_READ_WRITE) {
} else if (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED) {
access = GENERIC_READ | GENERIC_WRITE;
} else if (access_type == OS_FILE_READ_ALLOW_DELETE) {

Expand Down Expand Up @@ -1595,7 +1623,8 @@ os_file_create_simple_no_error_handling_func(
} else {

ut_a(access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_ALLOW_DELETE);
|| access_type == OS_FILE_READ_ALLOW_DELETE
|| access_type == OS_FILE_READ_WRITE_CACHED);

create_flag = O_RDWR;
}
Expand Down Expand Up @@ -1627,18 +1656,16 @@ os_file_create_simple_no_error_handling_func(
/* This function is always called for data files, we should disable
OS caching (O_DIRECT) here as we do in os_file_create_func(), so
we open the same file in the same mode, see man page of open(2). */
if (!srv_read_only_mode
&& *success
&& (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
|| srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {

os_file_set_nocache(file, name, mode_str);
if (*success) {
os_file_set_nocache_if_needed(file, name, mode_str,
OS_DATA_FILE, access_type);
}

#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
&& access_type == OS_FILE_READ_WRITE
&& (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED)
&& os_file_lock(file, name)) {

*success = FALSE;
Expand Down Expand Up @@ -1677,7 +1704,7 @@ UNIV_INTERN
void
os_file_set_nocache(
/*================*/
int fd /*!< in: file descriptor to alter */
os_file_t fd /*!< in: file descriptor to alter */
__attribute__((unused)),
const char* file_name /*!< in: used in the diagnostic
message */
Expand Down Expand Up @@ -2007,13 +2034,8 @@ os_file_create_func(

/* We disable OS caching (O_DIRECT) only on data files */

if (!srv_read_only_mode
&& *success
&& type != OS_LOG_FILE
&& (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
|| srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {

os_file_set_nocache(file, name, mode_str);
if (*success) {
os_file_set_nocache_if_needed(file, name, mode_str, type, 0);
}

#ifdef USE_FILE_LOCK
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/row/row0merge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3454,7 +3454,7 @@ row_merge_file_create(

if (merge_file->fd >= 0) {
if (srv_disable_sort_file_cache) {
os_file_set_nocache(merge_file->fd,
os_file_set_nocache((os_file_t)merge_file->fd,
"row0merge.cc", "sort");
}
}
Expand Down
5 changes: 4 additions & 1 deletion storage/xtradb/fil/fil0fil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3240,9 +3240,12 @@ 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, &success, 0);
OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0);

if (!success) {
/* The following call will print an error message */
Expand Down
20 changes: 12 additions & 8 deletions storage/xtradb/os/os0file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
Copyright (c) 2013, 2016, MariaDB Corporation.

Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
Expand Down Expand Up @@ -1422,7 +1422,8 @@ os_file_create_simple_func(

access = GENERIC_READ;

} else if (access_type == OS_FILE_READ_WRITE) {
} else if (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED) {
access = GENERIC_READ | GENERIC_WRITE;
} else {
ib_logf(IB_LOG_LEVEL_ERROR,
Expand Down Expand Up @@ -1526,7 +1527,8 @@ os_file_create_simple_func(
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
&& access_type == OS_FILE_READ_WRITE
&& (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED)
&& os_file_lock(file, name)) {

*success = FALSE;
Expand Down Expand Up @@ -1554,15 +1556,16 @@ os_file_set_nocache_if_needed(os_file_t file, const char* name,
const char *mode_str, ulint type,
ulint access_type)
{
if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED)
if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) {
return;
}

if (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT
|| (type != OS_LOG_FILE
|| (type == OS_LOG_FILE
&& (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
|| (srv_unix_file_flush_method
== SRV_UNIX_O_DIRECT_NO_FSYNC))))
|| (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)))) {
os_file_set_nocache(file, name, mode_str);
}
}

/****************************************************************//**
Expand Down Expand Up @@ -2154,8 +2157,9 @@ os_file_create_func(

} while (retry);

if (*success) {
/* We disable OS caching (O_DIRECT) only on data files */

if (*success) {
os_file_set_nocache_if_needed(file, name, mode_str, type, 0);
}

Expand Down

0 comments on commit f71c45c

Please sign in to comment.