diff options
Diffstat (limited to 'storage/xtradb/fil/fil0fil.cc')
-rw-r--r-- | storage/xtradb/fil/fil0fil.cc | 168 |
1 files changed, 109 insertions, 59 deletions
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 11fb999d529..dde309f4234 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -460,7 +460,7 @@ fil_space_get_latch( /*******************************************************************//** Returns the type of a file space. -@return FIL_TABLESPACE or FIL_LOG */ +@return ULINT_UNDEFINED, or FIL_TABLESPACE or FIL_LOG */ UNIV_INTERN ulint fil_space_get_type( @@ -468,6 +468,7 @@ fil_space_get_type( ulint id) /*!< in: space id */ { fil_space_t* space; + ulint type = ULINT_UNDEFINED; ut_ad(fil_system); @@ -475,11 +476,13 @@ fil_space_get_type( space = fil_space_get_by_id(id); - ut_a(space); - mutex_exit(&fil_system->mutex); - return(space->purpose); + if (space) { + type = space->purpose; + } + + return(type); } #endif /* !UNIV_HOTBACKUP */ @@ -2012,8 +2015,6 @@ fil_read_first_page( lsn values in data files */ lsn_t* max_flushed_lsn, /*!< out: max of flushed lsn values in data files */ - ulint orig_space_id, /*!< in: original file space - id */ fil_space_crypt_t** crypt_data) /*< out: crypt data */ { byte* buf; @@ -2022,6 +2023,7 @@ fil_read_first_page( const char* check_msg = NULL; fil_space_crypt_t* cdata; + buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE)); /* Align the memory for a possible read from a raw device */ @@ -2052,6 +2054,10 @@ fil_read_first_page( fsp_flags_get_zip_size(*flags), NULL); cdata = fil_space_read_crypt_data(space, page, offset); + if (crypt_data) { + *crypt_data = cdata; + } + /* If file space is encrypted we need to have at least some encryption service available where to get keys */ if ((cdata && cdata->encryption == FIL_SPACE_ENCRYPTION_ON) || @@ -2059,16 +2065,14 @@ fil_read_first_page( cdata && cdata->encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) { if (!encryption_key_id_exists(cdata->key_id)) { - ib_logf(IB_LOG_LEVEL_FATAL, - "Tablespace id %ld encrypted but encryption service" - " not available. Can't continue opening tablespace.\n", - space); - ut_error; - } - } + ib_logf(IB_LOG_LEVEL_ERROR, + "Tablespace id %ld is encrypted but encryption service" + " or used key_id %u is not available. Can't continue opening tablespace.", + space, cdata->key_id); - if (crypt_data) { - *crypt_data = cdata; + return ("table encrypted but encryption service not available."); + + } } ut_free(buf); @@ -2425,7 +2429,9 @@ fil_op_log_parse_or_replay( if (fil_create_new_single_table_tablespace( space_id, name, path, flags, DICT_TF2_USE_TABLESPACE, - FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) { + FIL_IBD_FILE_INITIAL_SIZE, + FIL_SPACE_ENCRYPTION_DEFAULT, + FIL_DEFAULT_ENCRYPTION_KEY) != DB_SUCCESS) { ut_error; } } @@ -3364,9 +3370,11 @@ fil_create_new_single_table_tablespace( const char* dir_path, /*!< in: NULL or a dir path */ ulint flags, /*!< in: tablespace flags */ ulint flags2, /*!< in: table flags2 */ - ulint size) /*!< in: the initial size of the + ulint size, /*!< in: the initial size of the tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ + fil_encryption_t mode, /*!< in: encryption mode */ + ulint key_id) /*!< in: encryption key_id */ { os_file_t file; ibool ret; @@ -3533,7 +3541,7 @@ fil_create_new_single_table_tablespace( } success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE, - fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY)); + fil_space_create_crypt_data(mode, key_id)); if (!success || !fil_node_create(path, size, space_id, FALSE)) { err = DB_ERROR; @@ -3650,7 +3658,8 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: tablespace flags */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* path_in) /*!< in: tablespace filepath */ + const char* path_in, /*!< in: tablespace filepath */ + dict_table_t* table) /*!< in: table */ { dberr_t err = DB_SUCCESS; bool dict_filepath_same_as_default = false; @@ -3761,9 +3770,13 @@ fil_open_single_table_tablespace( if (def.success) { def.check_msg = fil_read_first_page( def.file, FALSE, &def.flags, &def.id, - &def.lsn, &def.lsn, id, &def.crypt_data); + &def.lsn, &def.lsn, &def.crypt_data); def.valid = !def.check_msg; + if (table) { + table->crypt_data = def.crypt_data; + } + /* Validate this single-table-tablespace with SYS_TABLES, but do not compare the DATA_DIR flag, in case the tablespace was relocated. */ @@ -3783,9 +3796,13 @@ fil_open_single_table_tablespace( if (remote.success) { remote.check_msg = fil_read_first_page( remote.file, FALSE, &remote.flags, &remote.id, - &remote.lsn, &remote.lsn, id, &remote.crypt_data); + &remote.lsn, &remote.lsn, &remote.crypt_data); remote.valid = !remote.check_msg; + if (table) { + table->crypt_data = remote.crypt_data; + } + /* Validate this single-table-tablespace with SYS_TABLES, but do not compare the DATA_DIR flag, in case the tablespace was relocated. */ @@ -3806,9 +3823,13 @@ fil_open_single_table_tablespace( if (dict.success) { dict.check_msg = fil_read_first_page( dict.file, FALSE, &dict.flags, &dict.id, - &dict.lsn, &dict.lsn, id, &dict.crypt_data); + &dict.lsn, &dict.lsn, &dict.crypt_data); dict.valid = !dict.check_msg; + if (table) { + table->crypt_data = dict.crypt_data; + } + /* Validate this single-table-tablespace with SYS_TABLES, but do not compare the DATA_DIR flag, in case the tablespace was relocated. */ @@ -3990,7 +4011,9 @@ cleanup_and_exit: mem_free(remote.filepath); } if (remote.crypt_data && remote.crypt_data != crypt_data) { - fil_space_destroy_crypt_data(&remote.crypt_data); + if (err == DB_SUCCESS) { + fil_space_destroy_crypt_data(&remote.crypt_data); + } } if (dict.success) { os_file_close(dict.file); @@ -4005,7 +4028,9 @@ cleanup_and_exit: os_file_close(def.file); } if (def.crypt_data && def.crypt_data != crypt_data) { - fil_space_destroy_crypt_data(&def.crypt_data); + if (err == DB_SUCCESS) { + fil_space_destroy_crypt_data(&def.crypt_data); + } } mem_free(def.filepath); @@ -4225,7 +4250,7 @@ check_first_page: fsp->success = TRUE; if (const char* check_msg = fil_read_first_page( fsp->file, FALSE, &fsp->flags, &fsp->id, - &fsp->lsn, &fsp->lsn, ULINT_UNDEFINED, &fsp->crypt_data)) { + &fsp->lsn, &fsp->lsn, &fsp->crypt_data)) { ib_logf(IB_LOG_LEVEL_ERROR, "%s in tablespace %s (table %s)", check_msg, fsp->filepath, tablename); @@ -5923,9 +5948,9 @@ _fil_io( if (!ret) { return(DB_OUT_OF_FILE_SPACE); - } else { - return(DB_SUCCESS); } + + return(DB_SUCCESS); } #ifndef UNIV_HOTBACKUP @@ -6450,8 +6475,17 @@ fil_iterate( ut_ad(!(n_bytes % iter.page_size)); byte* readptr = io_buffer; - if (iter.crypt_data != NULL) { + byte* writeptr = io_buffer; + bool encrypted = false; + + /* Use additional crypt io buffer if tablespace is encrypted */ + if ((iter.crypt_data != NULL && iter.crypt_data->encryption == FIL_SPACE_ENCRYPTION_ON) || + (srv_encrypt_tables && + iter.crypt_data && iter.crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) { + + encrypted = true; readptr = iter.crypt_io_buffer; + writeptr = iter.crypt_io_buffer; } if (!os_file_read(iter.file, readptr, offset, (ulint) n_bytes)) { @@ -6464,24 +6498,36 @@ fil_iterate( bool updated = false; os_offset_t page_off = offset; ulint n_pages_read = (ulint) n_bytes / iter.page_size; + bool decrypted = false; for (ulint i = 0; i < n_pages_read; ++i) { + ulint size = iter.page_size; + dberr_t err = DB_SUCCESS; + + /* If tablespace is encrypted, we need to decrypt + the page. */ + if (encrypted) { + decrypted = fil_space_decrypt( + iter.crypt_data, + io_buffer + i * size, //dst + iter.page_size, + readptr + i * size, // src + &err); // src + + if (err != DB_SUCCESS) { + return(err); + } - if (iter.crypt_data != NULL) { - bool decrypted = fil_space_decrypt( - iter.crypt_data, - readptr + i * iter.page_size, // src - iter.page_size, - io_buffer + i * iter.page_size); // dst if (decrypted) { - /* write back unencrypted page */ updated = true; + } else { + /* TODO: remove unnecessary memcpy's */ + memcpy(io_buffer + i * size, readptr + i * size, size); } } buf_block_set_file_page(block, space_id, page_no++); - dberr_t err; if ((err = callback(page_off, block)) != DB_SUCCESS) { @@ -6495,6 +6541,32 @@ fil_iterate( buf_block_set_state(block, BUF_BLOCK_NOT_USED); buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE); + /* If tablespace is encrypted, encrypt page before we + write it back. Note that we should not encrypt the + buffer that is in buffer pool. */ + if (decrypted && encrypted) { + unsigned char *src = io_buffer + (i * size); + unsigned char *dst = writeptr + (i * size); + ulint space = mach_read_from_4( + src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + ulint offset = mach_read_from_4(src + FIL_PAGE_OFFSET); + ib_uint64_t lsn = mach_read_from_8(src + FIL_PAGE_LSN); + + byte* tmp = fil_encrypt_buf( + iter.crypt_data, + space, + offset, + lsn, + src, + iter.page_size == UNIV_PAGE_SIZE ? 0 : iter.page_size, + dst); + + if (tmp == src) { + /* TODO: remove unnecessary memcpy's */ + memcpy(writeptr, src, size); + } + } + page_off += iter.page_size; block->frame += iter.page_size; } @@ -6502,7 +6574,7 @@ fil_iterate( /* A page was updated in the set, write back to disk. */ if (updated && !os_file_write( - iter.filepath, iter.file, io_buffer, + iter.filepath, iter.file, writeptr, offset, (ulint) n_bytes)) { ib_logf(IB_LOG_LEVEL_ERROR, "os_file_write() failed"); @@ -6664,28 +6736,6 @@ fil_tablespace_iterate( mem_free(io_buffer); if (iter.crypt_data != NULL) { - /* clear crypt data from page 0 and write it back */ - os_file_read(file, page, 0, UNIV_PAGE_SIZE); - fil_space_clear_crypt_data(page, crypt_data_offset); - lsn_t lsn = mach_read_from_8(page + FIL_PAGE_LSN); - if (callback.get_zip_size() == 0) { - buf_flush_init_for_writing( - page, 0, lsn); - } else { - buf_flush_update_zip_checksum( - page, callback.get_zip_size(), lsn); - } - - if (!os_file_write( - iter.filepath, iter.file, page, - 0, iter.page_size)) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "os_file_write() failed"); - - return(DB_IO_ERROR); - } - mem_free(crypt_io_buffer); iter.crypt_io_buffer = NULL; fil_space_destroy_crypt_data(&iter.crypt_data); |