Skip to content

Commit 517b56d

Browse files
author
Vidhya Sree Rajuladevi
committed
Merge branch 'mysql-8.4' into mysql-trunk
2 parents 932e743 + 75e795e commit 517b56d

File tree

3 files changed

+92
-111
lines changed

3 files changed

+92
-111
lines changed

storage/innobase/fil/fil0fil.cc

Lines changed: 44 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,6 @@ enum fil_operation_t {
328328
/** The null file address */
329329
fil_addr_t fil_addr_null = {FIL_NULL, 0};
330330

331-
/** Maximum number of pages to read to determine the space ID. */
332-
static const size_t MAX_PAGES_TO_READ = 1;
333-
334331
#ifndef UNIV_HOTBACKUP
335332
/** Maximum number of shards supported. */
336333
static const size_t MAX_SHARDS = 68;
@@ -1627,9 +1624,12 @@ class Fil_system {
16271624
mapping table. */
16281625
dberr_t scan() { return m_dirs.scan(); }
16291626

1630-
/** Get the tablespace ID from an .ibd and/or an undo tablespace. If the ID is
1631-
0 on the first page then try finding the ID with Datafile::find_space_id().
1632-
@param[in] filename File name to check
1627+
/** Get the tablespace ID from an .ibd and/or an undo tablespace. If the
1628+
read failed or the ID is 0 on the first page or there is a mismatch of
1629+
space_ids stored in FSP_SPACE_ID and FIL_PAGE_SPACE_ID, then try finding
1630+
the ID with Datafile::find_space_id(). This function should only be called
1631+
during server startup.
1632+
@param[in] filename File name to check
16331633
@return s_invalid_space_id if not found, otherwise the space ID */
16341634
[[nodiscard]] static space_id_t get_tablespace_id(
16351635
const std::string &filename);
@@ -10954,116 +10954,62 @@ static bool fil_op_replay_rename(const page_id_t &page_id,
1095410954
return true;
1095510955
}
1095610956

10957-
/** Get the tablespace ID from an .ibd and/or an undo tablespace. If the ID is 0
10958-
on the first page then try finding the ID with Datafile::find_space_id().
10959-
@param[in] filename File name to check
10960-
@return s_invalid_space_id if not found, otherwise the space ID */
1096110957
space_id_t Fil_system::get_tablespace_id(const std::string &filename) {
10962-
FILE *fp = fopen(filename.c_str(), "rb");
10963-
10964-
if (fp == nullptr) {
10965-
ib::warn(ER_IB_MSG_372) << "Unable to open '" << filename << "'";
10966-
return dict_sys_t::s_invalid_space_id;
10967-
}
10958+
constexpr size_t read_size = UNIV_SECTOR_SIZE;
10959+
pfs_os_file_t file;
10960+
bool success;
1096810961

10969-
std::vector<space_id_t> space_ids;
10970-
auto page_size = srv_page_size;
10962+
/* Lambda function for heavy-duty method of finding the space id from
10963+
Datafile::find_space_id() which we fallback into, if the first page
10964+
cannot be read properly. */
10965+
const auto find_space_id_reliably = [&filename]() -> space_id_t {
10966+
Datafile data_file;
1097110967

10972-
space_ids.reserve(MAX_PAGES_TO_READ);
10968+
data_file.set_filepath(filename.c_str());
10969+
const dberr_t err = data_file.open_read_only(false);
1097310970

10974-
const auto n_bytes = page_size * MAX_PAGES_TO_READ;
10971+
ut_a(data_file.is_open());
10972+
ut_a(err == DB_SUCCESS);
1097510973

10976-
std::unique_ptr<byte[]> buf(new byte[n_bytes]);
10974+
/* Use the heavier Datafile::find_space_id() method to find the space id. */
10975+
return (data_file.find_space_id() == DB_SUCCESS)
10976+
? data_file.space_id()
10977+
: dict_sys_t::s_invalid_space_id;
10978+
};
1097710979

10978-
if (!buf) {
10980+
/* Open the file with O_DIRECT flag for faster access */
10981+
file = os_file_create(innodb_data_file_key, filename.c_str(), OS_FILE_OPEN,
10982+
OS_DATA_FILE_FOR_SPACE_ID_READ, true, &success);
10983+
if (!success) {
10984+
os_file_get_last_error(true);
10985+
ib::warn(ER_IB_MSG_372) << "Unable to open '" << filename << "'";
1097910986
return dict_sys_t::s_invalid_space_id;
1098010987
}
1098110988

10982-
auto pages_read = fread(buf.get(), page_size, MAX_PAGES_TO_READ, fp);
10983-
10984-
DBUG_EXECUTE_IF("invalid_header", pages_read = 0;);
10985-
10986-
/* Find the space id from the pages read if enough pages could be read.
10987-
Fall back to the more heavier method of finding the space id from
10988-
Datafile::find_space_id() if pages cannot be read properly. */
10989-
if (pages_read >= MAX_PAGES_TO_READ) {
10990-
auto bytes_read = pages_read * page_size;
10991-
10992-
#ifdef POSIX_FADV_DONTNEED
10993-
posix_fadvise(fileno(fp), 0, bytes_read, POSIX_FADV_DONTNEED);
10994-
#endif /* POSIX_FADV_DONTNEED */
10995-
10996-
for (page_no_t i = 0; i < MAX_PAGES_TO_READ; ++i) {
10997-
const auto off = i * page_size + FIL_PAGE_SPACE_ID;
10998-
10999-
if (off == FIL_PAGE_SPACE_ID) {
11000-
/* Find out the page size of the tablespace from the first page.
11001-
In case of compressed pages, the subsequent pages can be of different
11002-
sizes. If MAX_PAGES_TO_READ is changed to a different value, then the
11003-
page size of subsequent pages is needed to find out the offset for
11004-
space ID. */
11005-
11006-
auto space_flags_offset = FSP_HEADER_OFFSET + FSP_SPACE_FLAGS;
11007-
11008-
ut_a(space_flags_offset + 4 < n_bytes);
11009-
11010-
const auto flags = mach_read_from_4(buf.get() + space_flags_offset);
11011-
11012-
page_size_t space_page_size(flags);
11013-
11014-
page_size = space_page_size.physical();
11015-
}
11016-
11017-
space_ids.push_back(mach_read_from_4(buf.get() + off));
10989+
space_id_t space_id = dict_sys_t::s_invalid_space_id;
1101810990

11019-
if ((i + 1) * page_size >= bytes_read) {
11020-
break;
11021-
}
11022-
}
11023-
}
10991+
auto buf = ut::make_unique_aligned<byte[]>(read_size, read_size);
1102410992

11025-
fclose(fp);
10993+
IORequest request(IORequest::READ);
10994+
ulint bytes_read = 0;
1102610995

11027-
space_id_t space_id;
10996+
dberr_t err = os_file_read_no_error_handling(
10997+
request, filename.c_str(), file, buf.get(), 0, read_size, &bytes_read);
1102810998

11029-
if (!space_ids.empty()) {
11030-
space_id = space_ids.front();
10999+
os_file_close(file);
1103111000

11032-
for (auto id : space_ids) {
11033-
if (id == 0 || space_id != id) {
11034-
space_id = UINT32_UNDEFINED;
11001+
DBUG_EXECUTE_IF("invalid_header", bytes_read = 0;);
1103511002

11036-
break;
11037-
}
11038-
}
11039-
} else {
11040-
space_id = UINT32_UNDEFINED;
11003+
if (err != DB_SUCCESS || (bytes_read != read_size)) {
11004+
/* Reading from the first page failed, falling back to heavy duty method */
11005+
return find_space_id_reliably();
1104111006
}
1104211007

11043-
/* Try the more heavy duty method, as a last resort. */
11044-
if (space_id == UINT32_UNDEFINED) {
11045-
/* If the first page cannot be read properly, then for compressed
11046-
tablespaces we don't know where the page boundary starts because
11047-
we don't know the page size. */
11048-
11049-
Datafile file;
11050-
11051-
file.set_filepath(filename.c_str());
11052-
11053-
dberr_t err = file.open_read_only(false);
11054-
11055-
ut_a(file.is_open());
11056-
ut_a(err == DB_SUCCESS);
11057-
11058-
/* Use the heavier Datafile::find_space_id() method to
11059-
find the space id. */
11060-
err = file.find_space_id();
11061-
11062-
if (err == DB_SUCCESS) {
11063-
space_id = file.space_id();
11064-
}
11008+
/* Read the space_id from buf at offset FIL_PAGE_SPACE_ID */
11009+
space_id = fsp_header_get_space_id(buf.get());
1106511010

11066-
file.close();
11011+
if (space_id == 0 || space_id == SPACE_UNKNOWN) {
11012+
return find_space_id_reliably();
1106711013
}
1106811014

1106911015
return space_id;

storage/innobase/include/os0file.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ static const ulint OS_BUFFERED_FILE = 103;
231231
static const ulint OS_CLONE_DATA_FILE = 104;
232232
static const ulint OS_CLONE_LOG_FILE = 105;
233233
static const ulint OS_DBLWR_FILE = 106;
234+
static const ulint OS_DATA_FILE_FOR_SPACE_ID_READ = 107;
234235
/** @} */
235236

236237
/** Error codes from os_file_get_last_error @{ */
@@ -736,10 +737,12 @@ MY_COMPILER_DIAGNOSTIC_POP()
736737
@param[in] fd file descriptor to alter
737738
@param[in] file_name file name, used in the diagnostic message
738739
@param[in] operation_name "open" or "create"; used in the diagnostic
739-
message */
740+
message
741+
@param[in] on_error_silent if true then don't print any message to the log
742+
*/
740743
void os_file_set_nocache(int fd, const char *file_name,
741-
const char *operation_name);
742-
744+
const char *operation_name,
745+
bool on_error_silent = false);
743746
/** NOTE! Use the corresponding macro os_file_create(), not directly
744747
this function!
745748
Opens an existing file or creates a new.
@@ -1237,6 +1240,7 @@ static inline bool pfs_os_file_delete_if_exists_func(mysql_pfs_key_t key,
12371240

12381241
/* If UNIV_PFS_IO is not defined, these I/O APIs point
12391242
to original un-instrumented file I/O APIs */
1243+
12401244
#define os_file_create(key, name, create, purpose, read_only, success) \
12411245
os_file_create_func(name, create, purpose, read_only, success)
12421246

storage/innobase/os/os0file.cc

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
105105
#include <data0type.h>
106106
#endif /* UNIV_HOTBACKUP */
107107

108+
#ifndef _WIN32
109+
static_assert(OS_FILE_CLOSED == -1,
110+
"Our implementation for OSes other than Windows assumes an "
111+
"invalid handle is indicated by -1");
112+
#endif
113+
108114
/* Flush after each os_fsync_threshold bytes */
109115
unsigned long long os_fsync_threshold = 0;
110116

@@ -3152,7 +3158,7 @@ pfs_os_file_t os_file_create_func(const char *name, ulint create_mode,
31523158
ut_a(purpose == OS_LOG_FILE || purpose == OS_LOG_FILE_RESIZING ||
31533159
purpose == OS_DATA_FILE || purpose == OS_DBLWR_FILE ||
31543160
purpose == OS_CLONE_DATA_FILE || purpose == OS_CLONE_LOG_FILE ||
3155-
purpose == OS_BUFFERED_FILE);
3161+
purpose == OS_BUFFERED_FILE || OS_DATA_FILE_FOR_SPACE_ID_READ);
31563162

31573163
#ifdef O_SYNC
31583164
/* We let O_SYNC only affect log files; note that we map O_DSYNC to
@@ -3190,19 +3196,38 @@ pfs_os_file_t os_file_create_func(const char *name, ulint create_mode,
31903196

31913197
} while (retry);
31923198

3193-
/* We disable OS caching (O_DIRECT) only on data files. For clone we
3194-
need to set O_DIRECT even for read_only mode. */
3199+
if (!*success) {
3200+
ut_a(file.m_file == OS_FILE_CLOSED);
3201+
return file;
3202+
}
3203+
3204+
bool use_odirect = false;
31953205

3196-
if ((!read_only || purpose == OS_CLONE_DATA_FILE) && *success &&
3206+
if ((!read_only || purpose == OS_CLONE_DATA_FILE) &&
31973207
(purpose == OS_DATA_FILE || purpose == OS_CLONE_DATA_FILE ||
31983208
purpose == OS_DBLWR_FILE) &&
31993209
(srv_unix_file_flush_method == SRV_UNIX_O_DIRECT ||
32003210
srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
3201-
os_file_set_nocache(file.m_file, name, mode_str);
3211+
use_odirect = true;
3212+
}
3213+
3214+
/* We also set O_DIRECT for files which are opened at startup to
3215+
read their space ID from the page header */
3216+
if (purpose == OS_DATA_FILE_FOR_SPACE_ID_READ) {
3217+
use_odirect = true;
3218+
}
3219+
3220+
if (use_odirect) {
3221+
/* Flag for executing os_file_set_nocache() without printing error
3222+
messages */
3223+
const bool on_error_silent_for_nocache =
3224+
(purpose == OS_DATA_FILE_FOR_SPACE_ID_READ);
3225+
os_file_set_nocache(file.m_file, name, mode_str,
3226+
on_error_silent_for_nocache);
32023227
}
32033228

32043229
#ifdef USE_FILE_LOCK
3205-
if (!read_only && *success && create_mode != OS_FILE_OPEN_RAW &&
3230+
if (!read_only && create_mode != OS_FILE_OPEN_RAW &&
32063231
/* Don't acquire file lock while cloning files. */
32073232
purpose != OS_CLONE_DATA_FILE && purpose != OS_CLONE_LOG_FILE &&
32083233
os_file_lock(file.m_file, name)) {
@@ -4129,7 +4154,12 @@ pfs_os_file_t os_file_create_func(const char *name, ulint create_mode,
41294154
/* Do not use unbuffered i/o for the log files because
41304155
we write really a lot and we have log flusher for fsyncs. */
41314156

4132-
} else if (srv_win_file_flush_method == SRV_WIN_IO_UNBUFFERED) {
4157+
} else if (srv_win_file_flush_method == SRV_WIN_IO_UNBUFFERED ||
4158+
purpose == OS_DATA_FILE_FOR_SPACE_ID_READ) {
4159+
/* We use unbuffered access only when allowed by the
4160+
'srv_win_file_flush_method', unless the purpose is
4161+
to read the space ID on the startup, in which case
4162+
we should always use the unbuffered access */
41334163
attributes |= FILE_FLAG_NO_BUFFERING;
41344164
}
41354165
#endif /* UNIV_NON_BUFFERED_IO */
@@ -5257,10 +5287,11 @@ static bool os_file_handle_error_no_exit(const char *name,
52575287

52585288
void os_file_set_nocache(int fd [[maybe_unused]],
52595289
const char *file_name [[maybe_unused]],
5260-
const char *operation_name [[maybe_unused]]) {
5290+
const char *operation_name [[maybe_unused]],
5291+
bool on_error_silent [[maybe_unused]]) {
52615292
/* some versions of Solaris may not have DIRECTIO_ON */
52625293
#if defined(UNIV_SOLARIS) && defined(DIRECTIO_ON)
5263-
if (directio(fd, DIRECTIO_ON) == -1) {
5294+
if (directio(fd, DIRECTIO_ON) == -1 && !on_error_silent) {
52645295
int errno_save = errno;
52655296

52665297
ib::error(ER_IB_MSG_823)
@@ -5270,7 +5301,7 @@ void os_file_set_nocache(int fd [[maybe_unused]],
52705301
" continuing anyway.";
52715302
}
52725303
#elif defined(O_DIRECT)
5273-
if (fcntl(fd, F_SETFL, O_DIRECT) == -1) {
5304+
if (fcntl(fd, F_SETFL, O_DIRECT) == -1 && !on_error_silent) {
52745305
int errno_save = errno;
52755306
static bool warning_message_printed = false;
52765307
if (errno_save == EINVAL) {

0 commit comments

Comments
 (0)