Commit a74b01ea authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-16548 - Innodb fails to start on older kernels that don't support F_DUPFD_CLOEXEC

InnoDB duplicates file descriptor returned by create_temp_file() to
workaround further inconsistent use of this descriptor.

Use mysys file descriptors consistently for innobase_mysql_tmpfile(path).
Mostly close it by appropriate mysys wrappers.
parent 5f5a0b3b
......@@ -700,6 +700,7 @@ extern my_bool is_filename_allowed(const char *name, size_t length,
#ifdef _WIN32
/* Windows-only functions (CRT equivalents)*/
extern HANDLE my_get_osfhandle(File fd);
extern File my_win_handle2File(HANDLE hFile);
extern void my_osmaperr(unsigned long last_error);
#endif
......
......@@ -12,7 +12,7 @@ SET DEBUG_SYNC = 'now WAIT_FOR go';
select count_star into @final_count from performance_schema.events_waits_summary_global_by_event_name WHERE event_name LIKE '%wait%io%file%innodb%innodb_temp_file%';
SELECT @final_count - @init_count;
@final_count - @init_count
11
10
SET DEBUG_SYNC = 'now SIGNAL gone';
connection ddl;
disconnect ddl;
......
......@@ -501,13 +501,12 @@ static File my_get_stdfile_descriptor(FILE *stream)
}
File my_win_fileno(FILE *file)
File my_win_handle2File(HANDLE hFile)
{
HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file));
int retval= -1;
uint i;
DBUG_ENTER("my_win_fileno");
DBUG_ENTER("my_win_handle2File");
for(i= MY_FILE_MIN; i < my_file_limit; i++)
{
......@@ -517,6 +516,14 @@ File my_win_fileno(FILE *file)
break;
}
}
DBUG_RETURN(retval);
}
File my_win_fileno(FILE *file)
{
DBUG_ENTER("my_win_fileno");
int retval= my_win_handle2File((HANDLE) _get_osfhandle(fileno(file)));
if(retval == -1)
/* try std stream */
DBUG_RETURN(my_get_stdfile_descriptor(file));
......
......@@ -2345,96 +2345,6 @@ static bool is_mysql_datadir_path(const char *path)
TRUE));
}
static int mysql_tmpfile_path(const char *path, const char *prefix)
{
DBUG_ASSERT(path != NULL);
DBUG_ASSERT((strlen(path) + strlen(prefix)) <= FN_REFLEN);
char filename[FN_REFLEN];
File fd = create_temp_file(filename, path, prefix, O_BINARY | O_SEQUENTIAL,
MYF(MY_WME | MY_TEMPORARY));
return fd;
}
/** Creates a temporary file in the location specified by the parameter
path. If the path is NULL, then it will be created in tmpdir.
@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
os_file_t
innobase_mysql_tmpfile(
const char* path)
{
#ifdef WITH_INNODB_DISALLOW_WRITES
os_event_wait(srv_allow_writes_event);
#endif /* WITH_INNODB_DISALLOW_WRITES */
File fd;
DBUG_EXECUTE_IF(
"innobase_tmpfile_creation_failure",
return(OS_FILE_CLOSED);
);
if (path == NULL) {
fd = mysql_tmpfile("ib");
} else {
fd = mysql_tmpfile_path(path, "ib");
}
if (fd < 0)
return OS_FILE_CLOSED;
/* Copy the file descriptor, so that the additional resources
allocated by create_temp_file() can be freed by invoking
my_close().
Because the file descriptor returned by this function
will be passed to fdopen(), it will be closed by invoking
fclose(), which in turn will invoke close() instead of
my_close(). */
#ifdef _WIN32
/* Note that on Windows, the integer returned by mysql_tmpfile
has no relation to C runtime file descriptor. Here, we need
to call my_get_osfhandle to get the HANDLE and then convert it
to C runtime filedescriptor. */
HANDLE hFile = my_get_osfhandle(fd);
HANDLE hDup;
BOOL bOK = DuplicateHandle(
GetCurrentProcess(),
hFile, GetCurrentProcess(),
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
my_close(fd, MYF(MY_WME));
if (!bOK) {
my_osmaperr(GetLastError());
goto error;
}
return hDup;
#else
#ifdef F_DUPFD_CLOEXEC
int fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 0);
#else
int fd2 = dup(fd);
#endif
my_close(fd, MYF(MY_WME));
if (fd2 < 0) {
set_my_errno(errno);
goto error;
}
return fd2;
#endif
error:
char errbuf[MYSYS_STRERROR_SIZE];
my_error(EE_OUT_OF_FILERESOURCES,
MYF(0),
"ib*", errno,
my_strerror(errbuf, sizeof(errbuf), errno));
return (OS_FILE_CLOSED);
}
/*********************************************************************//**
Wrapper around MySQL's copy_and_convert function.
@return number of bytes copied to 'to' */
......
......@@ -1524,15 +1524,6 @@ os_file_get_status(
bool check_rw_perm,
bool read_only);
/** Creates a temporary file in the location specified by the parameter
path. If the path is NULL then it will be created on --tmpdir location.
This function is defined in ha_innodb.cc.
@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
os_file_t
innobase_mysql_tmpfile(
const char* path);
/** Set the file create umask
@param[in] umask The umask to use for file creation. */
void
......
......@@ -1029,12 +1029,12 @@ DECLARE_THREAD(fts_parallel_tokenization)(
crypt_block[i], table->space_id);
if (error != DB_SUCCESS) {
os_file_close(tmpfd[i]);
row_merge_file_destroy_low(tmpfd[i]);
goto func_exit;
}
total_rec += merge_file[i]->n_rec;
os_file_close(tmpfd[i]);
row_merge_file_destroy_low(tmpfd[i]);
}
func_exit:
......
......@@ -4093,6 +4093,9 @@ pfs_os_file_t
row_merge_file_create_low(
const char* path)
{
#ifdef WITH_INNODB_DISALLOW_WRITES
os_event_wait(srv_allow_writes_event);
#endif /* WITH_INNODB_DISALLOW_WRITES */
#ifdef UNIV_PFS_IO
/* This temp file open does not go through normal
file APIs, add instrumentation to register with
......@@ -4113,7 +4116,13 @@ row_merge_file_create_low(
PSI_FILE_CREATE, path ? name : label, __FILE__, __LINE__);
#endif
pfs_os_file_t fd = innobase_mysql_tmpfile(path);
DBUG_ASSERT(strlen(path) + 2 <= FN_REFLEN);
char filename[FN_REFLEN];
File f = create_temp_file(filename, path, "ib",
O_BINARY | O_SEQUENTIAL,
MYF(MY_WME | MY_TEMPORARY));
pfs_os_file_t fd = IF_WIN(my_get_osfhandle(f), f);
#ifdef UNIV_PFS_IO
register_pfs_file_open_end(locker, fd,
(fd == OS_FILE_CLOSED)?NULL:&fd);
......@@ -4158,7 +4167,9 @@ row_merge_file_destroy_low(
const pfs_os_file_t& fd) /*!< in: merge file descriptor */
{
if (fd != OS_FILE_CLOSED) {
os_file_close(fd);
int res = mysql_file_close(IF_WIN(my_win_handle2File(fd), fd),
MYF(MY_WME));
ut_a(res != -1);
}
}
/*********************************************************************//**
......
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