diff options
Diffstat (limited to 'storage/innobase/buf/buf0buf.cc')
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 188 |
1 files changed, 152 insertions, 36 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 152c7d13747..cff1cda47f1 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -57,6 +57,7 @@ Created 11/5/1995 Heikki Tuuri #include "dict0dict.h" #include "log0recv.h" #include "srv0mon.h" +#include "log0crypt.h" #include "fil0pagecompress.h" #include "fsp0pagecompress.h" #endif /* !UNIV_INNOCHECKSUM */ @@ -472,6 +473,45 @@ buf_pool_register_chunk( chunk->blocks->frame, chunk)); } +/** Decrypt a page for temporary tablespace. +@param[in,out] tmp_frame Temporary buffer +@param[in] src_frame Page to decrypt +@return true if temporary tablespace decrypted, false if not */ +static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame) +{ + if (buf_page_is_zeroes(src_frame, srv_page_size)) { + return true; + } + + /* read space & lsn */ + uint header_len = FIL_PAGE_DATA; + + /* Copy FIL page header, it is not encrypted */ + memcpy(tmp_frame, src_frame, header_len); + + /* Calculate the offset where decryption starts */ + const byte* src = src_frame + header_len; + byte* dst = tmp_frame + header_len; + uint srclen = uint(srv_page_size) + - header_len - FIL_PAGE_DATA_END; + ulint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET); + + if (!log_tmp_block_decrypt(src, srclen, dst, + (offset * srv_page_size))) { + return false; + } + + memcpy(tmp_frame + srv_page_size - FIL_PAGE_DATA_END, + src_frame + srv_page_size - FIL_PAGE_DATA_END, + FIL_PAGE_DATA_END); + + memcpy(src_frame, tmp_frame, srv_page_size); + srv_stats.pages_decrypted.inc(); + srv_stats.n_temp_blocks_decrypted.inc(); + + return true; /* page was decrypted */ +} + /** Decrypt a page. @param[in,out] bpage Page control block @param[in,out] space tablespace @@ -492,6 +532,22 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space) return (true); } + if (space->purpose == FIL_TYPE_TEMPORARY + && innodb_encrypt_temporary_tables) { + buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool); + buf_tmp_reserve_crypt_buf(slot); + + if (!buf_tmp_page_decrypt(slot->crypt_buf, dst_frame)) { + slot->release(); + ib::error() << "Encrypted page " << bpage->id + << " in file " << space->chain.start->name; + return false; + } + + slot->release(); + return true; + } + /* Page is encrypted if encryption information is found from tablespace and page contains used key_version. This is true also for pages first compressed and then encrypted. */ @@ -1076,25 +1132,30 @@ buf_page_is_corrupted( /* A page filled with NUL bytes is considered not corrupted. The FIL_PAGE_FILE_FLUSH_LSN field may be written nonzero for the first page of each file of the system tablespace. - Ignore it for the system tablespace. */ + We want to ignore it for the system tablespace, but because + we do not know the expected tablespace here, we ignore the + field for all data files, except for + innodb_checksum_algorithm=full_crc32 which we handled above. */ if (!checksum_field1 && !checksum_field2) { - ulint i = 0; - do { - if (read_buf[i]) { - return true; + /* Checksum fields can have valid value as zero. + If the page is not empty then do the checksum + calculation for the page. */ + bool all_zeroes = true; + for (size_t i = 0; i < srv_page_size; i++) { +#ifndef UNIV_INNOCHECKSUM + if (i == FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) { + i += 8; } - } while (++i < FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); - - /* Ignore FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION unless - innodb_checksum_algorithm=full_crc32. */ - i += 8; - - do { +#endif if (read_buf[i]) { - return true; + all_zeroes = false; + break; } - } while (++i < srv_page_size); - return false; + } + + if (all_zeroes) { + return false; + } } switch (curr_algo) { @@ -1283,14 +1344,16 @@ buf_madvise_do_dump() @param[in] zip_size compressed page size, or 0 */ void buf_page_print(const byte* read_buf, ulint zip_size) { - const ulint size = zip_size ? zip_size : srv_page_size; dict_index_t* index; +#ifndef UNIV_DEBUG + const ulint size = zip_size ? zip_size : srv_page_size; ib::info() << "Page dump in ascii and hex (" << size << " bytes):"; ut_print_buf(stderr, read_buf, size); fputs("\nInnoDB: End of page dump\n", stderr); +#endif if (zip_size) { /* Print compressed page. */ @@ -1934,7 +1997,7 @@ buf_pool_init_instance( buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size); - buf_pool->last_printout_time = ut_time(); + buf_pool->last_printout_time = time(NULL); } /* 2. Initialize flushing fields -------------------------------- */ @@ -2748,7 +2811,7 @@ buf_pool_resize() buf_resize_status("Withdrawing blocks to be shrunken."); - ib_time_t withdraw_started = ut_time(); + time_t withdraw_started = time(NULL); ulint message_interval = 60; ulint retry_interval = 1; @@ -2774,8 +2837,10 @@ withdraw_retry: /* abort buffer pool load */ buf_load_abort(); + const time_t current_time = time(NULL); + if (should_retry_withdraw - && ut_difftime(ut_time(), withdraw_started) >= message_interval) { + && difftime(current_time, withdraw_started) >= message_interval) { if (message_interval > 900) { message_interval = 1800; @@ -2791,8 +2856,7 @@ withdraw_retry: trx = UT_LIST_GET_NEXT(trx_list, trx)) { if (trx->state != TRX_STATE_NOT_STARTED && trx->mysql_thd != NULL - && ut_difftime(withdraw_started, - trx->start_time) > 0) { + && withdraw_started > trx->start_time) { if (!found) { ib::warn() << "The following trx might hold" @@ -2805,13 +2869,13 @@ withdraw_retry: } lock_trx_print_wait_and_mvcc_state( - stderr, trx); + stderr, trx, current_time); } } mutex_exit(&trx_sys.mutex); lock_mutex_exit(); - withdraw_started = ut_time(); + withdraw_started = current_time; } if (should_retry_withdraw) { @@ -6291,7 +6355,7 @@ void buf_refresh_io_stats( buf_pool_t* buf_pool) { - buf_pool->last_printout_time = ut_time(); + buf_pool->last_printout_time = time(NULL); buf_pool->old_stat = buf_pool->stat; } @@ -7354,6 +7418,44 @@ operator<<( return(out); } +/** Encrypt a buffer of temporary tablespace +@param[in] offset Page offset +@param[in] src_frame Page to encrypt +@param[in,out] dst_frame Output buffer +@return encrypted buffer or NULL */ +static byte* buf_tmp_page_encrypt( + ulint offset, + byte* src_frame, + byte* dst_frame) +{ + uint header_len = FIL_PAGE_DATA; + /* FIL page header is not encrypted */ + memcpy(dst_frame, src_frame, header_len); + + /* Calculate the start offset in a page */ + uint unencrypted_bytes = header_len + FIL_PAGE_DATA_END; + uint srclen = srv_page_size - unencrypted_bytes; + const byte* src = src_frame + header_len; + byte* dst = dst_frame + header_len; + + if (!log_tmp_block_encrypt(src, srclen, dst, (offset * srv_page_size), + true)) { + return NULL; + } + + memcpy(dst_frame + srv_page_size - FIL_PAGE_DATA_END, + src_frame + srv_page_size - FIL_PAGE_DATA_END, + FIL_PAGE_DATA_END); + + /* Handle post encryption checksum */ + mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, + buf_calc_page_crc32(dst_frame)); + + srv_stats.pages_encrypted.inc(); + srv_stats.n_temp_blocks_encrypted.inc(); + return dst_frame; +} + /** Encryption and page_compression hook that is called just before a page is written to disk. @param[in,out] space tablespace @@ -7387,13 +7489,20 @@ buf_page_encrypt( fil_space_crypt_t* crypt_data = space->crypt_data; - const bool encrypted = crypt_data - && !crypt_data->not_encrypted() - && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED - && (!crypt_data->is_default_encryption() - || srv_encrypt_tables); + bool encrypted, page_compressed; - bool page_compressed = space->is_compressed(); + if (space->purpose == FIL_TYPE_TEMPORARY) { + ut_ad(!crypt_data); + encrypted = innodb_encrypt_temporary_tables; + page_compressed = false; + } else { + encrypted = crypt_data + && !crypt_data->not_encrypted() + && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED + && (!crypt_data->is_default_encryption() + || srv_encrypt_tables); + page_compressed = space->is_compressed(); + } if (!encrypted && !page_compressed) { /* No need to encrypt or page compress the page. @@ -7433,18 +7542,25 @@ buf_page_encrypt( if (!page_compressed) { not_compressed: - /* Encrypt page content */ - byte* tmp = fil_space_encrypt(space, - bpage->id.page_no(), - bpage->newest_modification, - src_frame, - dst_frame); + byte* tmp; + if (space->purpose == FIL_TYPE_TEMPORARY) { + /* Encrypt temporary tablespace page content */ + tmp = buf_tmp_page_encrypt(bpage->id.page_no(), + src_frame, dst_frame); + } else { + /* Encrypt page content */ + tmp = fil_space_encrypt( + space, bpage->id.page_no(), + bpage->newest_modification, + src_frame, dst_frame); + } bpage->real_size = srv_page_size; slot->out_buf = dst_frame = tmp; ut_d(fil_page_type_validate(space, tmp)); } else { + ut_ad(space->purpose != FIL_TYPE_TEMPORARY); /* First we compress the page content */ buf_tmp_reserve_compression_buf(slot); byte* tmp = slot->comp_buf; |