summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/encryption/r/load_infile.result26
-rw-r--r--mysql-test/suite/encryption/t/load_infile.test73
-rw-r--r--storage/innobase/buf/buf0buf.cc17
-rw-r--r--storage/innobase/buf/buf0lru.cc15
-rw-r--r--storage/innobase/include/buf0buf.h20
-rw-r--r--storage/innobase/include/buf0lru.h2
-rw-r--r--storage/innobase/row/row0row.cc6
7 files changed, 155 insertions, 4 deletions
diff --git a/mysql-test/suite/encryption/r/load_infile.result b/mysql-test/suite/encryption/r/load_infile.result
new file mode 100644
index 00000000000..33cba74c71e
--- /dev/null
+++ b/mysql-test/suite/encryption/r/load_infile.result
@@ -0,0 +1,26 @@
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[0-9][0-9]*, page number=4\\] in file '.*test.t2\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: Error code: .* btr_pcur_open_low level: 0 called from file: .*");
+SET GLOBAL innodb_encryption_threads = 4;
+CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=YES;
+select * into outfile "/home/thiru/mariarepo/10.4/bld/mysql-test/var/tmp/t1.outfile" from t1;
+select count(*) from t1;
+count(*)
+10
+CREATE TABLE t2 (pk INT, c CHAR(255)) ENGINE=INNODB ENCRYPTED=YES;
+insert into t2 values(999, "sql"), (2000, "server"), (100, "mariadb"),
+(101, "mariadb"), (102, "test1"), (103, "test2"), (104, "test3");
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+select count(*) from t2;
+count(*)
+448
+# Corrupt the pages
+# restart
+load data infile '/home/thiru/mariarepo/10.4/bld/mysql-test/var/tmp/t1.outfile' into table t2;
+ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
+drop table t1, t2;
+SET GLOBAL innodb_encryption_threads=default;
diff --git a/mysql-test/suite/encryption/t/load_infile.test b/mysql-test/suite/encryption/t/load_infile.test
new file mode 100644
index 00000000000..6d3e1581684
--- /dev/null
+++ b/mysql-test/suite/encryption/t/load_infile.test
@@ -0,0 +1,73 @@
+-- source include/have_innodb.inc
+-- source include/have_file_key_management_plugin.inc
+
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[0-9][0-9]*, page number=4\\] in file '.*test.t2\\.ibd' cannot be decrypted\\.");
+
+call mtr.add_suppression("InnoDB: Error code: .* btr_pcur_open_low level: 0 called from file: .*");
+
+--disable_query_log
+let $encrypt_tables = `SELECT @@innodb_encrypt_tables`;
+let $threads = `SELECT @@innodb_encryption_threads`;
+let $key_id = `SELECT @@innodb_default_encryption_key_id`;
+--enable_query_log
+
+SET GLOBAL innodb_encryption_threads = 4;
+
+CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=YES;
+
+--disable_warnings
+--disable_query_log
+begin;
+let $i = 10;
+while ($i)
+{
+INSERT INTO t1 values(NULL, substring(MD5(RAND()), -128));
+dec $i;
+}
+commit;
+--enable_warnings
+--enable_query_log
+
+let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
+let MYSQLD_DATADIR=`select @@datadir`;
+
+eval select * into outfile "$MYSQLTEST_VARDIR/tmp/t1.outfile" from t1;
+
+select count(*) from t1;
+
+CREATE TABLE t2 (pk INT, c CHAR(255)) ENGINE=INNODB ENCRYPTED=YES;
+
+insert into t2 values(999, "sql"), (2000, "server"), (100, "mariadb"),
+ (101, "mariadb"), (102, "test1"), (103, "test2"), (104, "test3");
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+
+select count(*) from t2;
+
+--source include/shutdown_mysqld.inc
+--echo # Corrupt the pages
+
+perl;
+my $ps = $ENV{INNODB_PAGE_SIZE};
+
+my $file = "$ENV{MYSQLD_DATADIR}/test/t2.ibd";
+open(FILE, "+<$file") || die "Unable to open $file";
+binmode FILE;
+seek (FILE, $ENV{INNODB_PAGE_SIZE} * 4, SEEK_SET) or die "seek";
+print FILE "junk";
+close FILE or die "close";
+EOF
+
+--source include/start_mysqld.inc
+
+--error ER_GET_ERRMSG
+eval load data infile '$MYSQLTEST_VARDIR/tmp/t1.outfile' into table t2;
+
+drop table t1, t2;
+--remove_file $MYSQLTEST_VARDIR/tmp/t1.outfile
+
+SET GLOBAL innodb_encryption_threads=default;
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 37dd04f0d8e..d6472c6221f 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -4835,6 +4835,22 @@ evict_from_pool:
and block->lock. */
buf_wait_for_read(fix_block);
+ if (fix_block->page.id.is_corrupt_id()) {
+
+ fix_block->unfix();
+
+ if (err) {
+ *err = DB_PAGE_CORRUPTED;
+ }
+
+#ifdef UNIV_DEBUG
+ if (!fsp_is_system_temporary(page_id.space())) {
+ rw_lock_s_unlock(fix_block->debug_latch);
+ }
+#endif /* UNIV_DEBUG */
+ return NULL;
+ }
+
mtr_memo_type_t fix_type;
switch (rw_latch) {
@@ -5788,7 +5804,6 @@ buf_mark_space_corrupt(buf_page_t* bpage, const fil_space_t* space)
buf_pool_mutex_enter(buf_pool);
mutex_enter(buf_page_get_mutex(bpage));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
- ut_ad(bpage->buf_fix_count == 0);
ut_ad(bpage->id.space() == space->id);
/* Set BUF_IO_NONE before we remove the block from LRU list */
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 397ff8efa42..719225d4c92 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -2142,7 +2142,7 @@ Remove one page from LRU list and put it to free list */
void
buf_LRU_free_one_page(
/*==================*/
- buf_page_t* bpage) /*!< in/out: block, must contain a file page and
+ buf_page_t* bpage) /*!< in/out: block, must contain a file page and
be in a state where it can be freed; there
may or may not be a hash index to the page */
{
@@ -2153,7 +2153,20 @@ buf_LRU_free_one_page(
ut_ad(buf_pool_mutex_own(buf_pool));
+ page_id_t old_page_id(bpage->id.space(), bpage->id.page_no());
+
+ bpage->id.set_corrupt_id();
+
rw_lock_x_lock(hash_lock);
+
+ while (bpage->buf_fix_count > 0) {
+ /* Wait for other threads to release the fix count
+ before releasing the bpage from LRU list. */
+ }
+
+ bpage->id.set_space(old_page_id.space());
+ bpage->id.set_page_no(old_page_id.page_no());
+
mutex_enter(block_mutex);
if (buf_LRU_block_remove_hashed(bpage, true)) {
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index c6f693b1dc2..fb35c30eaf8 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -264,6 +264,26 @@ public:
ut_ad(page_no <= 0xFFFFFFFFU);
}
+ /** Set the space id
+ @param[in space space id */
+ inline void set_space(ulint space)
+ {
+ m_space = uint32_t(space);
+ }
+
+ /** Set the FIL_NULL for the space and page_no */
+ inline void set_corrupt_id()
+ {
+ m_space = m_page_no = FIL_NULL;
+ }
+
+ /** Check whether the corrupted page id
+ @return true if it is corrupted. */
+ inline bool is_corrupt_id()
+ {
+ return m_space == FIL_NULL && m_page_no == FIL_NULL;
+ }
+
private:
/** Tablespace id. */
diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h
index 81a257b0371..49b653802ca 100644
--- a/storage/innobase/include/buf0lru.h
+++ b/storage/innobase/include/buf0lru.h
@@ -207,7 +207,7 @@ Remove one page from LRU list and put it to free list */
void
buf_LRU_free_one_page(
/*==================*/
- buf_page_t* bpage) /*!< in/out: block, must contain a file page and
+ buf_page_t* bpage) /*!< in/out: block, must contain a file page and
be in a state where it can be freed; there
may or may not be a hash index to the page */
MY_ATTRIBUTE((nonnull));
diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
index c200e6fb15c..b62ec1fb870 100644
--- a/storage/innobase/row/row0row.cc
+++ b/storage/innobase/row/row0row.cc
@@ -1214,7 +1214,11 @@ row_search_on_row_ref(
& REC_INFO_MIN_REC_FLAG;
} else {
ut_a(ref->n_fields == index->n_uniq);
- btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr);
+
+ if (btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr)
+ != DB_SUCCESS) {
+ return FALSE;
+ }
}
low_match = btr_pcur_get_low_match(pcur);