[Commits] 6914704: MDEV-9236: Dramatically overallocation of InnoDB buffer pool leads to crash

Jan Lindström jan.lindstrom at mariadb.com
Thu Dec 17 19:46:36 EET 2015


revision-id: 69147040a66b90e8c861ce11a13f208d2a0680a2 (mariadb-10.1.9-21-g6914704)
parent(s): 670bc0b352187e1b62752b317971c037d783e8db
committer: Jan Lindström
timestamp: 2015-12-17 19:45:42 +0200
message:

MDEV-9236: Dramatically overallocation of InnoDB buffer pool leads to crash

Part I: Add diagnostics to page allocation if state is not correct
but do not assert if it is incorrect.

---
 storage/innobase/buf/buf0buf.cc     |  3 +++
 storage/innobase/buf/buf0lru.cc     |  4 +++-
 storage/innobase/include/buf0buf.h  | 12 +++++++++++-
 storage/innobase/include/buf0buf.ic | 35 +++++++++++++++++++++++++++++++++++
 storage/innobase/include/fil0fil.ic |  4 ++--
 storage/xtradb/buf/buf0buf.cc       |  3 +++
 storage/xtradb/buf/buf0lru.cc       |  4 +++-
 storage/xtradb/include/buf0buf.h    | 12 +++++++++++-
 storage/xtradb/include/buf0buf.ic   | 35 +++++++++++++++++++++++++++++++++++
 storage/xtradb/include/fil0fil.ic   |  4 ++--
 10 files changed, 108 insertions(+), 8 deletions(-)

diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 8445a45..f4e7c0d 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1452,6 +1452,9 @@ buf_pool_init_instance(
 
 	buf_pool_mutex_exit(buf_pool);
 
+	DBUG_EXECUTE_IF("buf_pool_init_instance_force_oom",
+		return(DB_ERROR); );
+
 	return(DB_SUCCESS);
 }
 
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 952f0fc..7591e44 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -2090,7 +2090,9 @@ buf_LRU_block_free_non_file_page(
 	case BUF_BLOCK_READY_FOR_USE:
 		break;
 	default:
-		ut_error;
+		fprintf(stderr, "InnoDB: Error: Block %p incorrect state %s in buf_LRU_block_free_non_file_page()\n",
+			block, buf_get_state_name(block));
+		return; /* Continue */
 	}
 
 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 6c8e8e0..985bddd 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -863,7 +863,17 @@ UNIV_INLINE
 enum buf_page_state
 buf_page_get_state(
 /*===============*/
-	const buf_page_t*	bpage);	/*!< in: pointer to the control block */
+	const buf_page_t*	bpage);	/*!< in: pointer to the control
+					block */
+/*********************************************************************//**
+Gets the state name for state of a block
+ at return	name or "CORRUPTED" */
+UNIV_INLINE
+const char*
+buf_get_state_name(
+/*===============*/
+	const buf_block_t*	block);	/*!< in: pointer to the control
+					block */
 /*********************************************************************//**
 Gets the state of a block.
 @return	state */
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index a80a4c0..5b66d65 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -233,6 +233,41 @@ buf_block_get_state(
 {
 	return(buf_page_get_state(&block->page));
 }
+
+/*********************************************************************//**
+Gets the state name for state of a block
+ at return	name or "CORRUPTED" */
+UNIV_INLINE
+const char*
+buf_get_state_name(
+/*===============*/
+	const buf_block_t*	block)	/*!< in: pointer to the control
+					block */
+{
+	enum buf_page_state	state = buf_page_get_state(&block->page);
+
+	switch (state) {
+	case BUF_BLOCK_POOL_WATCH:
+		return (const char *) "BUF_BLOCK_POOL_WATCH";
+	case BUF_BLOCK_ZIP_PAGE:
+		return (const char *) "BUF_BLOCK_ZIP_PAGE";
+	case BUF_BLOCK_ZIP_DIRTY:
+		return (const char *) "BUF_BLOCK_ZIP_DIRTY";
+	case BUF_BLOCK_NOT_USED:
+		return (const char *) "BUF_BLOCK_NOT_USED";
+	case BUF_BLOCK_READY_FOR_USE:
+		return (const char *) "BUF_BLOCK_NOT_USED";
+	case BUF_BLOCK_FILE_PAGE:
+		return (const char *) "BUF_BLOCK_FILE_PAGE";
+	case BUF_BLOCK_MEMORY:
+		return (const char *) "BUF_BLOCK_MEMORY";
+	case BUF_BLOCK_REMOVE_HASH:
+		return (const char *) "BUF_BLOCK_REMOVE_HASH";
+	default:
+		return (const char *) "CORRUPTED";
+	}
+}
+
 /*********************************************************************//**
 Sets the state of a block. */
 UNIV_INLINE
diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic
index f929123..a0bfb27 100644
--- a/storage/innobase/include/fil0fil.ic
+++ b/storage/innobase/include/fil0fil.ic
@@ -146,9 +146,9 @@ fil_page_type_validate(
 
 		/* Dump out the page info */
 		fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n"
-			"InnoDB: key_version %u page_compressed %d lsn %lu compressed_len %lu\n",
+			"InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %lu compressed_len %lu\n",
 			space, offset, rspace->name, page_type, fil_get_page_type_name(page_type),
-			key_version, page_compressed, lsn, compressed_len);
+			key_version, page_compressed, page_compressed_encrypted, lsn, compressed_len);
 		fflush(stderr);
 
 		ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED ||
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index f413670..363c9e7 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -1508,6 +1508,9 @@ buf_pool_init_instance(
 
 	buf_pool->try_LRU_scan = TRUE;
 
+	DBUG_EXECUTE_IF("buf_pool_init_instance_force_oom",
+		return(DB_ERROR); );
+
 	return(DB_SUCCESS);
 }
 
diff --git a/storage/xtradb/buf/buf0lru.cc b/storage/xtradb/buf/buf0lru.cc
index f2ce261..b36136e 100644
--- a/storage/xtradb/buf/buf0lru.cc
+++ b/storage/xtradb/buf/buf0lru.cc
@@ -2237,7 +2237,9 @@ buf_LRU_block_free_non_file_page(
 	case BUF_BLOCK_READY_FOR_USE:
 		break;
 	default:
-		ut_error;
+		fprintf(stderr, "InnoDB: Error: Block %p incorrect state %s in buf_LRU_block_free_non_file_page()\n",
+			block, buf_get_state_name(block));
+		return; /* Continue */
 	}
 
 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index b35ab9d..da3216b 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -861,7 +861,17 @@ UNIV_INLINE
 enum buf_page_state
 buf_page_get_state(
 /*===============*/
-	const buf_page_t*	bpage);	/*!< in: pointer to the control block */
+	const buf_page_t*	bpage);	/*!< in: pointer to the control
+					block */
+/*********************************************************************//**
+Gets the state name for state of a block
+ at return	name or "CORRUPTED" */
+UNIV_INLINE
+const char*
+buf_get_state_name(
+/*===============*/
+	const buf_block_t*	block);	/*!< in: pointer to the control
+					block */
 /*********************************************************************//**
 Gets the state of a block.
 @return	state */
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 8c8a3c9..f7e5123 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -236,6 +236,41 @@ buf_block_get_state(
 {
 	return(buf_page_get_state(&block->page));
 }
+
+/*********************************************************************//**
+Gets the state name for state of a block
+ at return	name or "CORRUPTED" */
+UNIV_INLINE
+const char*
+buf_get_state_name(
+/*===============*/
+	const buf_block_t*	block)	/*!< in: pointer to the control
+					block */
+{
+	enum buf_page_state	state = buf_page_get_state(&block->page);
+
+	switch (state) {
+	case BUF_BLOCK_POOL_WATCH:
+		return (const char *) "BUF_BLOCK_POOL_WATCH";
+	case BUF_BLOCK_ZIP_PAGE:
+		return (const char *) "BUF_BLOCK_ZIP_PAGE";
+	case BUF_BLOCK_ZIP_DIRTY:
+		return (const char *) "BUF_BLOCK_ZIP_DIRTY";
+	case BUF_BLOCK_NOT_USED:
+		return (const char *) "BUF_BLOCK_NOT_USED";
+	case BUF_BLOCK_READY_FOR_USE:
+		return (const char *) "BUF_BLOCK_NOT_USED";
+	case BUF_BLOCK_FILE_PAGE:
+		return (const char *) "BUF_BLOCK_FILE_PAGE";
+	case BUF_BLOCK_MEMORY:
+		return (const char *) "BUF_BLOCK_MEMORY";
+	case BUF_BLOCK_REMOVE_HASH:
+		return (const char *) "BUF_BLOCK_REMOVE_HASH";
+	default:
+		return (const char *) "CORRUPTED";
+	}
+}
+
 /*********************************************************************//**
 Sets the state of a block. */
 UNIV_INLINE
diff --git a/storage/xtradb/include/fil0fil.ic b/storage/xtradb/include/fil0fil.ic
index 38ed11e..ec3b7e8 100644
--- a/storage/xtradb/include/fil0fil.ic
+++ b/storage/xtradb/include/fil0fil.ic
@@ -147,9 +147,9 @@ fil_page_type_validate(
 
 		/* Dump out the page info */
 		fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n"
-			"InnoDB: key_version %u page_compressed %d lsn %lu compressed_len %lu\n",
+			"InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %lu compressed_len %lu\n",
 			space, offset, rspace->name, page_type, fil_get_page_type_name(page_type),
-			key_version, page_compressed, lsn, compressed_len);
+			key_version, page_compressed, page_compressed_encrypted, lsn, compressed_len);
 		fflush(stderr);
 
 		ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED ||


More information about the commits mailing list