diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-27 14:49:20 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-27 14:49:39 +0200 |
commit | e82e216e374739d7cab022a86b48498aa9c33ad5 (patch) | |
tree | 1833233b74ad6cc5378f49a8b92b6417bb76332a | |
parent | eb6364619ff807645230479bf7d2eb87d1a4edb4 (diff) | |
download | mariadb-git-e82e216e374739d7cab022a86b48498aa9c33ad5.tar.gz |
MDEV-17849 Undo tablespace truncation recovery fails to shrink file
fil_space_t::add(): Replaces fil_node_create(), fil_node_create_low().
Let the caller pass fil_node_t::handle, to avoid having to close and
re-open files.
fil_node_t::read_page0(): Refactored from fil_node_open_file().
Read the first page of a data file.
fil_node_open_file(): Open the file only once.
srv_undo_tablespace_open(): Set the file handle for the opened
undo tablespace. This should ensure that ut_ad(file->is_open())
no longer fails in recv_add_trim().
xtrabackup_backup_func(): Remove some dead code.
xb_fil_cur_open(): Open files only if needed. Undo tablespaces
should already have been opened.
-rw-r--r-- | extra/mariabackup/fil_cur.cc | 7 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 64 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 372 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0space.cc | 13 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0sysspace.cc | 14 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 40 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 132 |
7 files changed, 254 insertions, 388 deletions
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 7b7cfb3c948..219ec8845d4 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -159,8 +159,11 @@ xb_fil_cur_open( /* In the backup mode we should already have a tablespace handle created by fil_ibd_load() unless it is a system tablespace. Otherwise we open the file here. */ - if (cursor->is_system() || srv_operation == SRV_OPERATION_RESTORE_DELTA - || xb_close_files) { + if (!node->is_open()) { + ut_ad(cursor->is_system() + || srv_operation == SRV_OPERATION_RESTORE_DELTA + || xb_close_files); + node->handle = os_file_create_simple_no_error_handling( 0, node->name, OS_FILE_OPEN, diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index e627826b8c4..0f29da9e78e 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3101,11 +3101,8 @@ xb_load_single_table_tablespace( ut_a(space != NULL); - if (!fil_node_create(file->filepath(), ulint(n_pages), space, - false, false)) { - ut_error; - } - + space->add(file->filepath(), OS_FILE_CLOSED, ulint(n_pages), + false, false); /* by opening the tablespace we forcing node and space objects in the cache to be populated with fields from space header */ fil_space_open(space->name); @@ -3781,22 +3778,17 @@ xb_filters_free() } /*********************************************************************//** -Creates or opens the log files and closes them. -@return DB_SUCCESS or error code */ +Create log file metadata. */ static -ulint +void open_or_create_log_file( /*====================*/ fil_space_t* space, - ibool* log_file_created, /*!< out: TRUE if new log file - created */ ulint i) /*!< in: log file number in group */ { char name[10000]; ulint dirnamelen; - *log_file_created = FALSE; - os_normalize_path(srv_log_group_home_dir); dirnamelen = strlen(srv_log_group_home_dir); @@ -3808,14 +3800,13 @@ open_or_create_log_file( name[dirnamelen++] = OS_PATH_SEPARATOR; } - sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); + sprintf(name + dirnamelen, "%s%zu", "ib_logfile", i); ut_a(fil_validate()); - ut_a(fil_node_create(name, ulint(srv_log_file_size >> srv_page_size_shift), - space, false, false)); - - return(DB_SUCCESS); + space->add(name, OS_FILE_CLOSED, + ulint(srv_log_file_size >> srv_page_size_shift), + false, false); } /*********************************************************************//** @@ -4124,13 +4115,6 @@ fail: xb_filters_init(); - { - ibool log_file_created; - ibool log_created = FALSE; - ibool log_opened = FALSE; - ulint err; - ulint i; - xb_fil_io_init(); srv_n_file_io_threads = srv_n_read_io_threads; @@ -4145,36 +4129,8 @@ fail: lock_sys_create(srv_lock_table_size); - for (i = 0; i < srv_n_log_files; i++) { - err = open_or_create_log_file(space, &log_file_created, i); - if (err != DB_SUCCESS) { - goto fail; - } - - if (log_file_created) { - log_created = TRUE; - } else { - log_opened = TRUE; - } - if ((log_opened && log_created)) { - msg( - "mariabackup: Error: all log files must be created at the same time.\n" - "mariabackup: All log files must be created also in database creation.\n" - "mariabackup: If you want bigger or smaller log files, shut down the\n" - "mariabackup: database and make sure there were no errors in shutdown.\n" - "mariabackup: Then delete the existing log files. Edit the .cnf file\n" - "mariabackup: and start the database again.\n"); - - goto fail; - } - } - - /* log_file_created must not be TRUE, if online */ - if (log_file_created) { - msg("mariabackup: Something wrong with source files...\n"); - goto fail; - } - + for (ulint i = 0; i < srv_n_log_files; i++) { + open_or_create_log_file(space, i); } /* create extra LSN dir if it does not exist. */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 6368d4b4751..7744c9079f2 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -465,36 +465,25 @@ fil_space_is_flushed( /** Append a file to the chain of files of a space. @param[in] name file name of a file that is not open -@param[in] size file size in entire database blocks -@param[in,out] space tablespace from fil_space_create() -@param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if the file could use atomic write +@param[in] handle file handle, or OS_FILE_CLOSED +@param[in] size file size in entire database pages +@param[in] is_raw whether this is a raw device +@param[in] atomic_write true if atomic write could be enabled @param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -static -fil_node_t* -fil_node_create_low( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages = ULINT_MAX) +or ULINT_MAX for unlimited +@return file object */ +fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, + ulint size, bool is_raw, bool atomic_write, + ulint max_pages) { fil_node_t* node; ut_ad(name != NULL); ut_ad(fil_system != NULL); - if (space == NULL) { - return(NULL); - } - node = reinterpret_cast<fil_node_t*>(ut_zalloc_nokey(sizeof(*node))); - node->handle = OS_FILE_CLOSED; + node->handle = handle; node->name = mem_strdup(name); @@ -511,56 +500,116 @@ fil_node_create_low( node->init_size = size; node->max_size = max_pages; - mutex_enter(&fil_system->mutex); - - space->size += size; - - node->space = space; + node->space = this; node->atomic_write = atomic_write; - UT_LIST_ADD_LAST(space->chain, node); + mutex_enter(&fil_system->mutex); + this->size += size; + UT_LIST_ADD_LAST(chain, node); + if (node->is_open()) { + fil_system->n_open++; + } mutex_exit(&fil_system->mutex); - return(node); + return node; } -/** Appends a new file to the chain of files of a space. File must be closed. -@param[in] name file name (file must be closed) -@param[in] size file size in database blocks, rounded downwards to - an integer -@param[in,out] space space where to append -@param[in] is_raw true if a raw device or a raw disk partition -@param[in] atomic_write true if the file could use atomic write -@param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -char* -fil_node_create( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages) +/** Read the first page of a data file. +@param[in] first whether this is the very first read +@return whether the page was found valid */ +bool fil_node_t::read_page0(bool first) { - fil_node_t* node; + ut_ad(mutex_own(&fil_system->mutex)); + ut_a(space->purpose != FIL_TYPE_LOG); + const page_size_t page_size(space->flags); + const ulint psize = page_size.physical(); + + os_offset_t size_bytes = os_file_get_size(handle); + ut_a(size_bytes != (os_offset_t) -1); + const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE * psize; + + if (size_bytes < min_size) { + ib::error() << "The size of the file " << name + << " is only " << size_bytes + << " bytes, should be at least " << min_size; + return false; + } - node = fil_node_create_low( - name, size, space, is_raw, atomic_write, max_pages); + byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize)); - return(node == NULL ? NULL : node->name); + /* Align the memory for file i/o if we might have O_DIRECT set */ + byte* page = static_cast<byte*>(ut_align(buf2, psize)); + IORequest request(IORequest::READ); + if (!os_file_read(request, handle, page, 0, psize)) { + ib::error() << "Unable to read first page of file " << name; + ut_free(buf2); + return false; + } + srv_stats.page0_read.add(1); + const ulint space_id = fsp_header_get_space_id(page); + ulint flags = fsp_header_get_flags(page); + const ulint size = fsp_header_get_field(page, FSP_SIZE); + const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT); + const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE + + page); + /* Try to read crypt_data from page 0 if it is not yet read. */ + if (!space->crypt_data) { + space->crypt_data = fil_space_read_crypt_data(page_size, page); + } + ut_free(buf2); + + if (!fsp_flags_is_valid(flags, space->id)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED + || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { + ib::error() + << "Expected tablespace flags " + << ib::hex(space->flags) + << " but found " << ib::hex(flags) + << " in the file " << name; + return false; + } + + flags = cflags; + } + + if (UNIV_UNLIKELY(space_id != space->id)) { + ib::error() << "Expected tablespace id " << space->id + << " but found " << space_id + << " in the file " << name; + return false; + } + + ut_ad(space->free_limit == 0 || space->free_limit == free_limit); + ut_ad(space->free_len == 0 || space->free_len == free_len); + space->size_in_header = size; + space->free_limit = free_limit; + space->free_len = free_len; + + if (first) { + /* Truncate the size to a multiple of extent size. */ + ulint mask = psize * FSP_EXTENT_SIZE - 1; + + if (size_bytes <= mask) { + /* .ibd files start smaller than an + extent size. Do not truncate valid data. */ + } else { + size_bytes &= ~os_offset_t(mask); + } + + this->size = ulint(size_bytes / psize); + space->size += this->size; + } + + return true; } /** Open a file node of a tablespace. The caller must own the fil_system mutex. @param[in,out] node File node @return false if the file can't be opened, otherwise true */ -static -bool -fil_node_open_file( - fil_node_t* node) +static bool fil_node_open_file(fil_node_t* node) { bool success; bool read_only_mode; @@ -588,9 +637,12 @@ fil_node_open_file( from a file opened for async I/O! */ retry: - node->handle = os_file_create_simple_no_error_handling( - innodb_data_file_key, node->name, OS_FILE_OPEN, - OS_FILE_READ_ONLY, read_only_mode, &success); + node->handle = os_file_create( + innodb_data_file_key, node->name, + node->is_raw_disk + ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT + : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, + OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); if (!success) { /* The following call prints an error message */ @@ -606,150 +658,47 @@ retry: return(false); } - os_offset_t size_bytes = os_file_get_size(node->handle); - ut_a(size_bytes != (os_offset_t) -1); - - ut_a(space->purpose != FIL_TYPE_LOG); - const page_size_t page_size(space->flags); - const ulint psize = page_size.physical(); - const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE - * psize; - - if (size_bytes < min_size) { - ib::error() << "The size of the file " << node->name - << " is only " << size_bytes - << " bytes, should be at least " << min_size; + if (!node->read_page0(first_time_open)) { os_file_close(node->handle); node->handle = OS_FILE_CLOSED; - return(false); - } - - /* Read the first page of the tablespace */ - - byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize)); - - /* Align the memory for file i/o if we might have O_DIRECT - set */ - byte* page = static_cast<byte*>(ut_align(buf2, psize)); - - IORequest request(IORequest::READ); - - success = os_file_read( - request, - node->handle, page, 0, psize); - srv_stats.page0_read.add(1); - - const ulint space_id - = fsp_header_get_space_id(page); - ulint flags = fsp_header_get_flags(page); - const ulint size = fsp_header_get_field( - page, FSP_SIZE); - const ulint free_limit = fsp_header_get_field( - page, FSP_FREE_LIMIT); - const ulint free_len = flst_get_len( - FSP_HEADER_OFFSET + FSP_FREE + page); - - /* Try to read crypt_data from page 0 if it is not yet - read. */ - if (!space->crypt_data) { - space->crypt_data = fil_space_read_crypt_data( - page_size_t(space->flags), page); - } - - ut_free(buf2); - os_file_close(node->handle); - node->handle = OS_FILE_CLOSED; - - if (!fsp_flags_is_valid(flags, space->id)) { - ulint cflags = fsp_flags_convert_from_101(flags); - if (cflags == ULINT_UNDEFINED - || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { - ib::error() - << "Expected tablespace flags " - << ib::hex(space->flags) - << " but found " << ib::hex(flags) - << " in the file " << node->name; - return(false); - } - - flags = cflags; - } - - if (UNIV_UNLIKELY(space_id != space->id)) { - ib::error() - << "Expected tablespace id " << space->id - << " but found " << space_id - << " in the file" << node->name; - return(false); + return false; } - - ut_ad(space->free_limit == 0 - || space->free_limit == free_limit); - ut_ad(space->free_len == 0 - || space->free_len == free_len); - space->size_in_header = size; - space->free_limit = free_limit; - space->free_len = free_len; - - if (first_time_open) { - /* Truncate the size to a multiple of extent size. */ - ulint mask = psize * FSP_EXTENT_SIZE - 1; - - if (size_bytes <= mask) { - /* .ibd files start smaller than an - extent size. Do not truncate valid data. */ - } else { - size_bytes &= ~os_offset_t(mask); - } - - node->size = ulint(size_bytes / psize); - space->size += node->size; - } - } - - /* printf("Opening file %s\n", node->name); */ - - /* Open the file for reading and writing, in Windows normally in the - unbuffered async I/O mode, though global variables may make - os_file_create() to fall back to the normal file I/O mode. */ - - if (space->purpose == FIL_TYPE_LOG) { + } else if (space->purpose == FIL_TYPE_LOG) { node->handle = os_file_create( innodb_log_file_key, node->name, OS_FILE_OPEN, OS_FILE_AIO, OS_LOG_FILE, read_only_mode, &success); - } else if (node->is_raw_disk) { - node->handle = os_file_create( - innodb_data_file_key, node->name, OS_FILE_OPEN_RAW, - OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); } else { node->handle = os_file_create( - innodb_data_file_key, node->name, OS_FILE_OPEN, + innodb_data_file_key, node->name, + node->is_raw_disk + ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT + : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); + } - if (first_time_open) { - /* - For the temporary tablespace and during the - non-redo-logged adjustments in - IMPORT TABLESPACE, we do not care about - the atomicity of writes. - - Atomic writes is supported if the file can be used - with atomic_writes (not log file), O_DIRECT is - used (tested in ha_innodb.cc) and the file is - device and file system that supports atomic writes - for the given block size - */ - space->atomic_write_supported - = space->purpose == FIL_TYPE_TEMPORARY - || space->purpose == FIL_TYPE_IMPORT - || (node->atomic_write - && srv_use_atomic_writes - && my_test_if_atomic_write( - node->handle, - int(page_size_t(space->flags) - .physical()))); - } - } + if (space->purpose != FIL_TYPE_LOG) { + /* + For the temporary tablespace and during the + non-redo-logged adjustments in + IMPORT TABLESPACE, we do not care about + the atomicity of writes. + + Atomic writes is supported if the file can be used + with atomic_writes (not log file), O_DIRECT is + used (tested in ha_innodb.cc) and the file is + device and file system that supports atomic writes + for the given block size + */ + space->atomic_write_supported + = space->purpose == FIL_TYPE_TEMPORARY + || space->purpose == FIL_TYPE_IMPORT + || (node->atomic_write + && srv_use_atomic_writes + && my_test_if_atomic_write( + node->handle, + int(page_size_t(space->flags) + .physical()))); + } ut_a(success); ut_a(node->is_open()); @@ -1430,7 +1379,7 @@ Error messages are issued to the server log. @param[in] purpose tablespace purpose @param[in,out] crypt_data encryption information @param[in] mode encryption mode -@return pointer to created tablespace, to be filled in with fil_node_create() +@return pointer to created tablespace, to be filled in with fil_space_t::add() @retval NULL on failure (such as when the same tablespace exists) */ fil_space_t* fil_space_create( @@ -1519,7 +1468,7 @@ fil_space_create( if (space->purpose == FIL_TYPE_TEMPORARY) { ut_d(space->latch.set_temp_fsp()); /* SysTablespace::open_or_create() would pass - size!=0 to fil_node_create(), so first_time_open + size!=0 to fil_space_t::add(), so first_time_open would not hold in fil_node_open_file(), and we must assign this manually. We do not care about the durability or atomicity of writes to the @@ -3819,22 +3768,16 @@ fil_ibd_create( space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE, crypt_data, mode); - - fil_node_t* node = NULL; - - if (space) { - node = fil_node_create_low(path, size, space, false, true); - } - - if (!space || !node) { + if (!space) { if (crypt_data) { free(crypt_data); } err = DB_ERROR; } else { - mtr_t mtr; - const fil_node_t* file = UT_LIST_GET_FIRST(space->chain); + mtr_t mtr; + fil_node_t* file = space->add(path, OS_FILE_CLOSED, size, + false, true); mtr.start(); fil_op_write_log( @@ -3843,7 +3786,7 @@ fil_ibd_create( fil_name_write(space, 0, file, &mtr); mtr.commit(); - node->block_size = block_size; + file->block_size = block_size; space->punch_hole = punch_hole; err = DB_SUCCESS; @@ -4072,6 +4015,7 @@ fil_ibd_open( || df_remote.is_open() != df_remote.is_valid()) { return(DB_CORRUPTION); } +error: return(DB_ERROR); } @@ -4180,17 +4124,17 @@ skip_validate: fil_space_t* space = fil_space_create( space_name, id, flags, purpose, crypt_data); + if (!space) { + goto error; + } /* We do not measure the size of the file, that is why we pass the 0 below */ - if (fil_node_create_low( - df_remote.is_open() ? df_remote.filepath() : - df_dict.is_open() ? df_dict.filepath() : - df_default.filepath(), 0, space, false, - true) == NULL) { - err = DB_ERROR; - } + space->add( + df_remote.is_open() ? df_remote.filepath() : + df_dict.is_open() ? df_dict.filepath() : + df_default.filepath(), OS_FILE_CLOSED, 0, false, true); if (err == DB_SUCCESS && validate && purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) { @@ -4539,9 +4483,7 @@ fil_ibd_load( the rounding formula for extents and pages is somewhat complex; we let fil_node_open() do that task. */ - if (!fil_node_create_low(file.filepath(), 0, space, false, false)) { - ut_error; - } + space->add(file.filepath(), OS_FILE_CLOSED, 0, false, false); return(FIL_LOAD_OK); } diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc index df234f7274e..88b34be4952 100644 --- a/storage/innobase/fsp/fsp0space.cc +++ b/storage/innobase/fsp/fsp0space.cc @@ -123,18 +123,15 @@ Tablespace::open_or_create(bool is_temp) is_temp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); - /* Create the tablespace node entry for this data file. */ - if (!fil_node_create( - it->m_filepath, it->m_size, space, false, - TRUE)) { - - err = DB_ERROR; - break; - } + space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size, + false, true); } return(err); diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index baf864bc1c3..b856bf3da74 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -918,6 +918,9 @@ SysTablespace::open_or_create( name(), space_id(), flags(), is_temp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); @@ -928,15 +931,8 @@ SysTablespace::open_or_create( : m_last_file_size_max) : it->m_size); - /* Add the datafile to the fil_system cache. */ - if (!fil_node_create( - it->m_filepath, it->m_size, - space, it->m_type != SRV_NOT_RAW, - TRUE, max_size)) { - - err = DB_ERROR; - break; - } + space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size, + it->m_type != SRV_NOT_RAW, true, max_size); } return(err); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index d1bd2dc14d4..6406ff8448c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -195,6 +195,19 @@ struct fil_space_t { return !atomic_write_supported && srv_use_doublewrite_buf && buf_dblwr; } + + /** Append a file to the chain of files of a space. + @param[in] name file name of a file that is not open + @param[in] handle file handle, or OS_FILE_CLOSED + @param[in] size file size in entire database pages + @param[in] is_raw whether this is a raw device + @param[in] atomic_write true if atomic write could be enabled + @param[in] max_pages maximum number of pages in file, + or ULINT_MAX for unlimited + @return file object */ + fil_node_t* add(const char* name, pfs_os_file_t handle, + ulint size, bool is_raw, bool atomic_write, + ulint max_pages = ULINT_MAX); }; /** Value of fil_space_t::magic_n */ @@ -252,6 +265,11 @@ struct fil_node_t { { return(handle != OS_FILE_CLOSED); } + + /** Read the first page of a data file. + @param[in] first whether this is the very first read + @return whether the page was found valid */ + bool read_page0(bool first); }; /** Value of fil_node_t::magic_n */ @@ -547,26 +565,6 @@ void fil_space_set_imported( ulint id); -/** Append a file to the chain of files of a space. -@param[in] name file name of a file that is not open -@param[in] size file size in entire database blocks -@param[in,out] space tablespace from fil_space_create() -@param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if atomic write could be enabled -@param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -char* -fil_node_create( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages = ULINT_MAX) - MY_ATTRIBUTE((warn_unused_result)); - /** Create a space memory object and put it to the fil_system hash table. Error messages are issued to the server log. @param[in] name tablespace name @@ -575,7 +573,7 @@ Error messages are issued to the server log. @param[in] purpose tablespace purpose @param[in,out] crypt_data encryption information @param[in] mode encryption mode -@return pointer to created tablespace, to be filled in with fil_node_create() +@return pointer to created tablespace, to be filled in with fil_space_t::add() @retval NULL on failure (such as when the same tablespace exists) */ fil_space_t* fil_space_create( diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 8719d26d5f3..ae890750841 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -470,23 +470,16 @@ create_log_files( const ulint size = ulint(srv_log_file_size >> srv_page_size_shift); - logfile0 = fil_node_create( - logfilename, size, log_space, false, false); + logfile0 = log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false)->name; ut_a(logfile0); for (unsigned i = 1; i < srv_n_log_files; i++) { sprintf(logfilename + dirnamelen, "ib_logfile%u", i); - if (!fil_node_create(logfilename, size, - log_space, false, false)) { - - ib::error() - << "Cannot create file node for log file " - << logfilename; - - return(DB_ERROR); - } + log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false); } log_init(srv_n_log_files); @@ -634,83 +627,68 @@ srv_undo_tablespace_create( return(err); } -/*********************************************************************//** -Open an undo tablespace. -@return DB_SUCCESS or error code */ -static -dberr_t -srv_undo_tablespace_open( -/*=====================*/ - const char* name, /*!< in: tablespace file name */ - ulint space_id) /*!< in: tablespace id */ + +/** Open an undo tablespace. +@param[in] name tablespace file name +@param[in] space_id tablespace ID +@param[in] create_new_db whether undo tablespaces are being created +@return whether the tablespace was opened */ +static bool srv_undo_tablespace_open(const char* name, ulint space_id, + bool create_new_db) { pfs_os_file_t fh; - bool ret; - dberr_t err = DB_ERROR; + bool success; char undo_name[sizeof "innodb_undo000"]; snprintf(undo_name, sizeof(undo_name), "innodb_undo%03u", static_cast<unsigned>(space_id)); - if (!srv_file_check_mode(name)) { - ib::error() << "UNDO tablespaces must be " << - (srv_read_only_mode ? "writable" : "readable") << "!"; - - return(DB_ERROR); - } - fh = os_file_create( - innodb_data_file_key, name, - OS_FILE_OPEN_RETRY - | OS_FILE_ON_ERROR_NO_EXIT - | OS_FILE_ON_ERROR_SILENT, - OS_FILE_NORMAL, - OS_DATA_FILE, - srv_read_only_mode, - &ret); - - /* If the file open was successful then load the tablespace. */ - - if (ret) { - os_offset_t size; - fil_space_t* space; - - size = os_file_get_size(fh); - ut_a(size != (os_offset_t) -1); + innodb_data_file_key, name, OS_FILE_OPEN + | OS_FILE_ON_ERROR_NO_EXIT | OS_FILE_ON_ERROR_SILENT, + OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success); + if (!success) { + return false; + } - ret = os_file_close(fh); - ut_a(ret); + os_offset_t size = os_file_get_size(fh); + ut_a(size != os_offset_t(-1)); - /* Load the tablespace into InnoDB's internal - data structures. */ + /* Load the tablespace into InnoDB's internal data structures. */ - /* We set the biggest space id to the undo tablespace - because InnoDB hasn't opened any other tablespace apart - from the system tablespace. */ + /* We set the biggest space id to the undo tablespace + because InnoDB hasn't opened any other tablespace apart + from the system tablespace. */ - fil_set_max_space_id_if_bigger(space_id); + fil_set_max_space_id_if_bigger(space_id); - space = fil_space_create( - undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), - FIL_TYPE_TABLESPACE, NULL); + fil_space_t* space = fil_space_create( + undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), + FIL_TYPE_TABLESPACE, NULL); - ut_a(fil_validate()); - ut_a(space); + ut_a(fil_validate()); + ut_a(space); - os_offset_t n_pages = size / UNIV_PAGE_SIZE; + fil_node_t* file = space->add(name, fh, 0, false, true); - /* On 32-bit platforms, ulint is 32 bits and os_offset_t - is 64 bits. It is OK to cast the n_pages to ulint because - the unit has been scaled to pages and page number is always - 32 bits. */ - if (fil_node_create( - name, (ulint) n_pages, space, false, TRUE)) { + mutex_enter(&fil_system->mutex); - err = DB_SUCCESS; + if (create_new_db) { + space->size = file->size = ulint(size >> srv_page_size_shift); + space->size_in_header = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; + } else { + success = file->read_page0(true); + if (!success) { + os_file_close(file->handle); + file->handle = OS_FILE_CLOSED; + ut_a(fil_system->n_open > 0); + fil_system->n_open--; } } - return(err); + mutex_exit(&fil_system->mutex); + + return success; } /** Check if undo tablespaces and redo log files exist before creating a @@ -936,12 +914,11 @@ srv_undo_tablespaces_init(bool create_new_db) ut_a(undo_tablespace_ids[i] != 0); ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); - err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); - - if (err != DB_SUCCESS) { + if (!srv_undo_tablespace_open(name, undo_tablespace_ids[i], + create_new_db)) { ib::error() << "Unable to open undo tablespace '" << name << "'."; - return(err); + return DB_ERROR; } prev_space_id = undo_tablespace_ids[i]; @@ -966,9 +943,8 @@ srv_undo_tablespaces_init(bool create_new_db) name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); - err = srv_undo_tablespace_open(name, i); - - if (err != DB_SUCCESS) { + if (!srv_undo_tablespace_open(name, i, create_new_db)) { + err = DB_ERROR; break; } @@ -2078,10 +2054,8 @@ innobase_start_or_create_for_mysql() for (unsigned j = 0; j < srv_n_log_files_found; j++) { sprintf(logfilename + dirnamelen, "ib_logfile%u", j); - if (!fil_node_create(logfilename, size, - log_space, false, false)) { - return(srv_init_abort(DB_ERROR)); - } + log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false); } log_init(srv_n_log_files_found); |