summaryrefslogtreecommitdiff
path: root/storage/innobase/buf/buf0buf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/buf/buf0buf.cc')
-rw-r--r--storage/innobase/buf/buf0buf.cc188
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;