List:Commits« Previous MessageNext Message »
From:marko.makela Date:March 24 2011 12:29pm
Subject:bzr push into mysql-5.5-innodb branch (marko.makela:3350 to 3351)
Bug#11766305
View as plain text  
 3351 Marko Mäkelä	2011-03-24
      Bug#11766305 - 59392: Remove thr0loc.c and ibuf_inside() [part 4 of 4]
      
      ibuf_inside(), ibuf_enter(), ibuf_exit(): Add the parameter mtr. The
      flag is no longer kept in the thread-local storage but in the
      mini-transaction (mtr->inside_ibuf).
      
      mtr_start(): Clean up the comment and remove the unused return value.
      mtr_commit(): Assert !ibuf_inside(mtr) in debug builds.
      
      ibuf_mtr_start(): Like mtr_start(), but sets the flag.
      ibuf_mtr_commit(), ibuf_btr_pcur_commit_specify_mtr(): Wrappers that
      assert ibuf_inside().
      
      buf_page_get_zip(), buf_page_init_for_read(),
      buf_read_ibuf_merge_pages(), fil_io(), ibuf_free_excess_pages(),
      ibuf_contract_ext(): Remove assertions on ibuf_inside(), because a
      mini-transaction is not available.
      
      buf_read_ahead_linear(): Add the parameter inside_ibuf.
      
      ibuf_restore_pos(): When this function returns FALSE, it commits mtr
      and must therefore do ibuf_exit(mtr).
      
      ibuf_delete_rec(): This function commits mtr and must therefore do
      ibuf_exit(mtr).
      
      ibuf_rec_get_page_no(), ibuf_rec_get_space(), ibuf_rec_get_info(),
      ibuf_rec_get_op_type(), ibuf_build_entry_from_ibuf_rec(),
      ibuf_rec_get_volume(), ibuf_get_merge_page_nos(),
      ibuf_get_volume_buffered_count(), ibuf_get_entry_counter_low(): Add
      the parameter mtr in debug builds, for asserting ibuf_inside(mtr).
      
      rb:585 approved by Sunny Bains

    removed:
      storage/innobase/include/thr0loc.h
      storage/innobase/include/thr0loc.ic
      storage/innobase/thr/
      storage/innobase/thr/thr0loc.c
    modified:
      storage/innobase/CMakeLists.txt
      storage/innobase/btr/btr0cur.c
      storage/innobase/buf/buf0buf.c
      storage/innobase/buf/buf0rea.c
      storage/innobase/fil/fil0fil.c
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/ibuf/ibuf0ibuf.c
      storage/innobase/include/buf0rea.h
      storage/innobase/include/ibuf0ibuf.h
      storage/innobase/include/ibuf0ibuf.ic
      storage/innobase/include/mtr0mtr.h
      storage/innobase/include/mtr0mtr.ic
      storage/innobase/include/sync0sync.h
      storage/innobase/mtr/mtr0mtr.c
      storage/innobase/srv/srv0srv.c
      storage/innobase/srv/srv0start.c
      storage/innobase/trx/trx0trx.c
 3350 Marko Mäkelä	2011-03-22
      Bug#11766305 - 59392: Remove thr0loc.c and ibuf_inside() [part 3]
      Remove the slot_no member of struct thr_local_struct.
      
      enum srv_thread_type: Remove unused thread types.
      srv_get_thread_type(): Unused function, remove.
      
      thr_local_get_slot_no(), thr_local_set_slot_no(): Remove.
      
      srv_thread_type_validate(), srv_slot_get_type(): New functions, for debugging.
      
      srv_table_reserve_slot(): Return the srv_slot_t* directly. Do not create
      thread-local storage.
      
      srv_suspend_thread(): Get the srv_slot_t* as parameter. Return void;
      the caller knows slot->event already.
      
      srv_thread_has_reserved_slot(), srv_release_threads(): Assert
      srv_thread_type_validate(type).
      
      srv_init(): Use mem_zalloc() instead of mem_alloc(). Replace
      srv_table_get_nth_slot(), because it now asserts that the kernel_mutex
      is being held.
      
      srv_master_thread(), srv_purge_thread(): Remember the slot from
      srv_table_reserve_slot().
      
      rb:629 approved by Inaam Rana

    modified:
      storage/innobase/include/srv0srv.h
      storage/innobase/include/thr0loc.h
      storage/innobase/srv/srv0srv.c
      storage/innobase/thr/thr0loc.c
=== modified file 'storage/innobase/CMakeLists.txt'
--- a/storage/innobase/CMakeLists.txt	revid:marko.makela@stripped2113916-oricw02qg3tzvim8
+++ b/storage/innobase/CMakeLists.txt	revid:marko.makela@stripped29qxj6lveq
@@ -241,7 +241,6 @@ SET(INNOBASE_SOURCES	btr/btr0btr.c btr/b
 			row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
 			srv/srv0srv.c srv/srv0start.c
 			sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
-			thr/thr0loc.c
 			trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
 			trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
 			usr/usr0sess.c

=== modified file 'storage/innobase/btr/btr0cur.c'
--- a/storage/innobase/btr/btr0cur.c	revid:marko.makela@stripped
+++ b/storage/innobase/btr/btr0cur.c	revid:marko.makela@strippedom-20110324120014-hk1iw529qxj6lveq
@@ -402,7 +402,7 @@ btr_cur_search_to_nth_level(
 
 	ut_ad(level == 0 || mode == PAGE_CUR_LE);
 	ut_ad(dict_index_check_search_tuple(index, tuple));
-	ut_ad(!dict_index_is_ibuf(index) || ibuf_inside());
+	ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
 	ut_ad(dtuple_check_typed(tuple));
 
 #ifdef UNIV_DEBUG

=== modified file 'storage/innobase/buf/buf0buf.c'
--- a/storage/innobase/buf/buf0buf.c	revid:marko.makela@stripped
+++ b/storage/innobase/buf/buf0buf.c	revid:marko.makela@stripped20110324120014-hk1iw529qxj6lveq
@@ -2316,9 +2316,6 @@ buf_page_get_zip(
 	unsigned	access_time;
 	buf_pool_t*	buf_pool = buf_pool_get(space, offset);
 
-#ifndef UNIV_LOG_DEBUG
-	ut_ad(!ibuf_inside());
-#endif
 	buf_pool->stat.n_page_gets++;
 
 	for (;;) {
@@ -2758,8 +2755,9 @@ buf_page_get_gen(
 	ut_ad(zip_size == fil_space_get_zip_size(space));
 	ut_ad(ut_is_2pow(zip_size));
 #ifndef UNIV_LOG_DEBUG
-	ut_ad(!ibuf_inside() || ibuf_page_low(space, zip_size, offset,
-					      FALSE, file, line, NULL));
+	ut_ad(!ibuf_inside(mtr)
+	      || ibuf_page_low(space, zip_size, offset,
+			       FALSE, file, line, NULL));
 #endif
 	buf_pool->stat.n_page_gets++;
 	fold = buf_page_address_fold(space, offset);
@@ -3132,7 +3130,8 @@ wait_until_unfixed:
 		/* In the case of a first access, try to apply linear
 		read-ahead */
 
-		buf_read_ahead_linear(space, zip_size, offset);
+		buf_read_ahead_linear(space, zip_size, offset,
+				      ibuf_inside(mtr));
 	}
 
 #ifdef UNIV_IBUF_COUNT_DEBUG
@@ -3189,7 +3188,7 @@ buf_page_optimistic_get(
 	access_time = buf_page_is_accessed(&block->page);
 	buf_page_set_accessed_make_young(&block->page, access_time);
 
-	ut_ad(!ibuf_inside()
+	ut_ad(!ibuf_inside(mtr)
 	      || ibuf_page(buf_block_get_space(block),
 			   buf_block_get_zip_size(block),
 			   buf_block_get_page_no(block), NULL));
@@ -3245,7 +3244,8 @@ buf_page_optimistic_get(
 
 		buf_read_ahead_linear(buf_block_get_space(block),
 				      buf_block_get_zip_size(block),
-				      buf_block_get_page_no(block));
+				      buf_block_get_page_no(block),
+				      ibuf_inside(mtr));
 	}
 
 #ifdef UNIV_IBUF_COUNT_DEBUG
@@ -3321,7 +3321,7 @@ buf_page_get_known_nowait(
 		buf_pool_mutex_exit(buf_pool);
 	}
 
-	ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
+	ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
 
 	if (rw_latch == RW_S_LATCH) {
 		success = rw_lock_s_lock_nowait(&(block->lock),
@@ -3586,14 +3586,13 @@ buf_page_init_for_read(
 		/* It is a read-ahead within an ibuf routine */
 
 		ut_ad(!ibuf_bitmap_page(zip_size, offset));
-		ut_ad(ibuf_inside());
 
-		mtr_start(&mtr);
+		ibuf_mtr_start(&mtr);
 
 		if (!recv_no_ibuf_operations
 		    && !ibuf_page(space, zip_size, offset, &mtr)) {
 
-			mtr_commit(&mtr);
+			ibuf_mtr_commit(&mtr);
 
 			return(NULL);
 		}
@@ -3778,7 +3777,7 @@ func_exit:
 
 	if (mode == BUF_READ_IBUF_PAGES_ONLY) {
 
-		mtr_commit(&mtr);
+		ibuf_mtr_commit(&mtr);
 	}
 
 	ut_ad(!bpage || buf_page_in_file(bpage));

=== modified file 'storage/innobase/buf/buf0rea.c'
--- a/storage/innobase/buf/buf0rea.c	revid:marko.makela@stripped
+++ b/storage/innobase/buf/buf0rea.c	revid:marko.makela@oracle.com-20110324120014-hk1iw529qxj6lveq
@@ -236,10 +236,10 @@ UNIV_INTERN
 ulint
 buf_read_ahead_linear(
 /*==================*/
-	ulint	space,	/*!< in: space id */
-	ulint	zip_size,/*!< in: compressed page size in bytes, or 0 */
-	ulint	offset)	/*!< in: page number of a page; NOTE: the current thread
-			must want access to this page (see NOTE 3 above) */
+	ulint	space,		/*!< in: space id */
+	ulint	zip_size,	/*!< in: compressed page size in bytes, or 0 */
+	ulint	offset,		/*!< in: page number; see NOTE 3 above */
+	ibool	inside_ibuf)	/*!< in: TRUE if we are inside ibuf routine */
 {
 	buf_pool_t*	buf_pool = buf_pool_get(space, offset);
 	ib_int64_t	tablespace_version;
@@ -429,11 +429,9 @@ buf_read_ahead_linear(
 
 	/* If we got this far, read-ahead can be sensible: do it */
 
-	if (ibuf_inside()) {
-		ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
-	} else {
-		ibuf_mode = BUF_READ_ANY_PAGE;
-	}
+	ibuf_mode = inside_ibuf
+		? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER
+		: BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER;
 
 	count = 0;
 
@@ -450,7 +448,7 @@ buf_read_ahead_linear(
 		if (!ibuf_bitmap_page(zip_size, i)) {
 			count += buf_read_page_low(
 				&err, FALSE,
-				ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
+				ibuf_mode,
 				space, zip_size, FALSE, tablespace_version, i);
 			if (err == DB_TABLESPACE_DELETED) {
 				ut_print_timestamp(stderr);
@@ -520,7 +518,6 @@ buf_read_ibuf_merge_pages(
 {
 	ulint	i;
 
-	ut_ad(!ibuf_inside());
 #ifdef UNIV_IBUF_DEBUG
 	ut_a(n_stored < UNIV_PAGE_SIZE);
 #endif

=== modified file 'storage/innobase/fil/fil0fil.c'
--- a/storage/innobase/fil/fil0fil.c	revid:marko.makela@strippedm-20110322113916-oricw02qg3tzvim8
+++ b/storage/innobase/fil/fil0fil.c	revid:marko.makela@stripped4-hk1iw529qxj6lveq
@@ -4342,8 +4342,6 @@ fil_io(
 	ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
 	      || !ibuf_bitmap_page(zip_size, block_offset)
 	      || sync || is_log);
-	ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
-	      || ibuf_page(space_id, zip_size, block_offset, NULL));
 # endif /* UNIV_LOG_DEBUG */
 	if (sync) {
 		mode = OS_AIO_SYNC;

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	revid:marko.makela@stripped0110322113916-oricw02qg3tzvim8
+++ b/storage/innobase/handler/ha_innodb.cc	revid:marko.makela@stripped20014-hk1iw529qxj6lveq
@@ -82,7 +82,6 @@ extern "C" {
 #include "fil0fil.h"
 #include "trx0xa.h"
 #include "row0merge.h"
-#include "thr0loc.h"
 #include "dict0boot.h"
 #include "ha_prototypes.h"
 #include "ut0mem.h"
@@ -280,7 +279,6 @@ static PSI_mutex_info all_innodb_mutexes
 	{&sync_thread_mutex_key, "sync_thread_mutex", 0},
 #  endif /* UNIV_SYNC_DEBUG */
 	{&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0},
-	{&thr_local_mutex_key, "thr_local_mutex", 0},
 	{&trx_undo_mutex_key, "trx_undo_mutex", 0}
 };
 # endif /* UNIV_PFS_MUTEX */
@@ -3042,7 +3040,6 @@ innobase_close_connection(
 
 	innobase_rollback_trx(trx);
 
-	thr_local_free(trx->mysql_thread_id);
 	trx_free_for_mysql(trx);
 
 	DBUG_RETURN(0);

=== modified file 'storage/innobase/ibuf/ibuf0ibuf.c'
--- a/storage/innobase/ibuf/ibuf0ibuf.c	revid:marko.makela@stripped16-oricw02qg3tzvim8
+++ b/storage/innobase/ibuf/ibuf0ibuf.c	revid:marko.makela@strippedxj6lveq
@@ -44,7 +44,6 @@ Created 7/19/1997 Heikki Tuuri
 #include "fsp0fsp.h"
 #include "trx0sys.h"
 #include "fil0fil.h"
-#include "thr0loc.h"
 #include "rem0rec.h"
 #include "btr0cur.h"
 #include "btr0pcur.h"
@@ -324,52 +323,43 @@ still physically like the index page eve
 dropped! So, there seems to be no problem. */
 
 /******************************************************************//**
-Sets the flag in the current OS thread local storage denoting that it is
+Sets the flag in the current mini-transaction record indicating we're
 inside an insert buffer routine. */
 UNIV_INLINE
 void
-ibuf_enter(void)
-/*============*/
+ibuf_enter(
+/*=======*/
+	mtr_t*	mtr)	/*!< in/out: mini-transaction */
 {
-	ibool*	ptr;
-
-	ptr = thr_local_get_in_ibuf_field();
-
-	ut_ad(*ptr == FALSE);
-
-	*ptr = TRUE;
+	ut_ad(!mtr->inside_ibuf);
+	mtr->inside_ibuf = TRUE;
 }
 
 /******************************************************************//**
-Sets the flag in the current OS thread local storage denoting that it is
+Sets the flag in the current mini-transaction record indicating we're
 exiting an insert buffer routine. */
 UNIV_INLINE
 void
-ibuf_exit(void)
-/*===========*/
+ibuf_exit(
+/*======*/
+	mtr_t*	mtr)	/*!< in/out: mini-transaction */
 {
-	ibool*	ptr;
-
-	ptr = thr_local_get_in_ibuf_field();
-
-	ut_ad(*ptr == TRUE);
-
-	*ptr = FALSE;
+	ut_ad(mtr->inside_ibuf);
+	mtr->inside_ibuf = FALSE;
 }
 
-/******************************************************************//**
-Returns TRUE if the current OS thread is performing an insert buffer
-routine.
-
-For instance, a read-ahead of non-ibuf pages is forbidden by threads
-that are executing an insert buffer routine.
-@return TRUE if inside an insert buffer routine */
-UNIV_INTERN
-ibool
-ibuf_inside(void)
-/*=============*/
+/**************************************************************//**
+Commits an insert buffer mini-transaction and sets the persistent
+cursor latch mode to BTR_NO_LATCHES, that is, detaches the cursor. */
+UNIV_INLINE
+void
+ibuf_btr_pcur_commit_specify_mtr(
+/*=============================*/
+	btr_pcur_t*	pcur,	/*!< in/out: persistent cursor */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
 {
-	return(*thr_local_get_in_ibuf_field());
+	ut_d(ibuf_exit(mtr));
+	btr_pcur_commit_specify_mtr(pcur, mtr);
 }
 
 /******************************************************************//**
@@ -379,11 +369,11 @@ static
 page_t*
 ibuf_header_page_get(
 /*=================*/
-	mtr_t*	mtr)	/*!< in: mtr */
+	mtr_t*	mtr)	/*!< in/out: mini-transaction */
 {
 	buf_block_t*	block;
 
-	ut_ad(!ibuf_inside());
+	ut_ad(!ibuf_inside(mtr));
 
 	block = buf_page_get(
 		IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
@@ -404,7 +394,7 @@ ibuf_tree_root_get(
 	buf_block_t*	block;
 	page_t*		root;
 
-	ut_ad(ibuf_inside());
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(mutex_own(&ibuf_mutex));
 
 	mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
@@ -547,7 +537,7 @@ ibuf_init_at_db_start(void)
 
 	fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
 			      &n_used, &mtr);
-	ibuf_enter();
+	ibuf_enter(&mtr);
 
 	ut_ad(n_used >= 2);
 
@@ -568,9 +558,7 @@ ibuf_init_at_db_start(void)
 	mutex_exit(&ibuf_mutex);
 
 	ibuf->empty = (page_get_n_recs(root) == 0);
-	mtr_commit(&mtr);
-
-	ibuf_exit();
+	ibuf_mtr_commit(&mtr);
 
 	heap = mem_heap_create(450);
 
@@ -1230,19 +1218,30 @@ ibuf_page_low(
 	return(ret);
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(rec)
+#endif /* UNIV_DEBUG */
+
 /********************************************************************//**
 Returns the page number field of an ibuf record.
 @return	page number */
 static
 ulint
-ibuf_rec_get_page_no(
-/*=================*/
+ibuf_rec_get_page_no_func(
+/*======================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	rec)	/*!< in: ibuf record */
 {
 	const byte*	field;
 	ulint		len;
 
-	ut_ad(ibuf_inside());
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(rec_get_n_fields_old(rec) > 2);
 
 	field = rec_get_nth_field_old(rec, 1, &len);
@@ -1264,20 +1263,31 @@ ibuf_rec_get_page_no(
 	return(mach_read_from_4(field));
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(rec)
+#endif /* UNIV_DEBUG */
+
 /********************************************************************//**
 Returns the space id field of an ibuf record. For < 4.1.x format records
 returns 0.
 @return	space id */
 static
 ulint
-ibuf_rec_get_space(
-/*===============*/
+ibuf_rec_get_space_func(
+/*====================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	rec)	/*!< in: ibuf record */
 {
 	const byte*	field;
 	ulint		len;
 
-	ut_ad(ibuf_inside());
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(rec_get_n_fields_old(rec) > 2);
 
 	field = rec_get_nth_field_old(rec, 1, &len);
@@ -1298,12 +1308,22 @@ ibuf_rec_get_space(
 	return(0);
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter)	\
+	ibuf_rec_get_info_func(mtr,rec,op,comp,info_len,counter)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter)	\
+	ibuf_rec_get_info_func(rec,op,comp,info_len,counter)
+#endif
 /****************************************************************//**
 Get various information about an ibuf record in >= 4.1.x format. */
 static
 void
-ibuf_rec_get_info(
-/*==============*/
+ibuf_rec_get_info_func(
+/*===================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	rec,		/*!< in: ibuf record */
 	ibuf_op_t*	op,		/*!< out: operation type, or NULL */
 	ibool*		comp,		/*!< out: compact flag, or NULL */
@@ -1322,7 +1342,9 @@ ibuf_rec_get_info(
 	ulint		info_len_local;
 	ulint		counter_local;
 
-	ut_ad(ibuf_inside());
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
 	fields = rec_get_n_fields_old(rec);
 	ut_a(fields > 4);
 
@@ -1371,18 +1393,29 @@ ibuf_rec_get_info(
 	}
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(rec)
+#endif
+
 /****************************************************************//**
 Returns the operation type field of an ibuf record.
 @return	operation type */
 static
 ibuf_op_t
-ibuf_rec_get_op_type(
-/*=================*/
+ibuf_rec_get_op_type_func(
+/*======================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	rec)	/*!< in: ibuf record */
 {
 	ulint		len;
 
-	ut_ad(ibuf_inside());
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(rec_get_n_fields_old(rec) > 2);
 
 	(void) rec_get_nth_field_old(rec, 1, &len);
@@ -1394,7 +1427,7 @@ ibuf_rec_get_op_type(
 	} else {
 		ibuf_op_t	op;
 
-		ibuf_rec_get_info(rec, &op, NULL, NULL, NULL);
+		ibuf_rec_get_info(mtr, rec, &op, NULL, NULL, NULL);
 
 		return(op);
 	}
@@ -1593,6 +1626,14 @@ ibuf_build_entry_pre_4_1_x(
 	return(tuple);
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex)	\
+	ibuf_build_entry_from_ibuf_rec_func(mtr,ibuf_rec,heap,pindex)
+#else /* UNIV_DEBUG */
+# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex)	\
+	ibuf_build_entry_from_ibuf_rec_func(ibuf_rec,heap,pindex)
+#endif
+
 /*********************************************************************//**
 Builds the entry used to
 
@@ -1611,8 +1652,11 @@ hold a latch to the ibuf_rec page as lon
 @return own: entry to insert to a non-clustered index */
 static
 dtuple_t*
-ibuf_build_entry_from_ibuf_rec(
-/*===========================*/
+ibuf_build_entry_from_ibuf_rec_func(
+/*================================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	ibuf_rec,	/*!< in: record in an insert buffer */
 	mem_heap_t*	heap,		/*!< in: heap where built */
 	dict_index_t**	pindex)		/*!< out, own: dummy index that
@@ -1629,6 +1673,10 @@ ibuf_build_entry_from_ibuf_rec(
 	ulint		comp;
 	dict_index_t*	index;
 
+	ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
+
 	data = rec_get_nth_field_old(ibuf_rec, 1, &len);
 
 	if (len > 1) {
@@ -1649,7 +1697,7 @@ ibuf_build_entry_from_ibuf_rec(
 
 	types = rec_get_nth_field_old(ibuf_rec, 3, &len);
 
-	ibuf_rec_get_info(ibuf_rec, NULL, &comp, &info_len, NULL);
+	ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL);
 
 	index = ibuf_dummy_index_create(n_fields, comp);
 
@@ -1736,6 +1784,12 @@ ibuf_rec_get_size(
 	return(size);
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_volume(mtr,rec) ibuf_rec_get_volume_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_volume(mtr,rec) ibuf_rec_get_volume_func(rec)
+#endif
+
 /********************************************************************//**
 Returns the space taken by a stored non-clustered index entry if converted to
 an index record.
@@ -1743,8 +1797,11 @@ an index record.
 taken in the page directory */
 static
 ulint
-ibuf_rec_get_volume(
-/*================*/
+ibuf_rec_get_volume_func(
+/*=====================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	ibuf_rec)/*!< in: ibuf record */
 {
 	ulint		len;
@@ -1755,7 +1812,9 @@ ibuf_rec_get_volume(
 	ibool		pre_4_1;
 	ulint		comp;
 
-	ut_ad(ibuf_inside());
+	ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
 
 	data = rec_get_nth_field_old(ibuf_rec, 1, &len);
@@ -1783,7 +1842,7 @@ ibuf_rec_get_volume(
 
 		types = rec_get_nth_field_old(ibuf_rec, 3, &len);
 
-		ibuf_rec_get_info(ibuf_rec, &op, &comp, &info_len, NULL);
+		ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL);
 
 		if (op == IBUF_OP_DELETE_MARK || op == IBUF_OP_DELETE) {
 			/* Delete-marking a record doesn't take any
@@ -1800,7 +1859,7 @@ ibuf_rec_get_volume(
 			mem_heap_t*	heap = mem_heap_create(500);
 
 			entry = ibuf_build_entry_from_ibuf_rec(
-				ibuf_rec, heap, &dummy_index);
+				mtr, ibuf_rec, heap, &dummy_index);
 
 			volume = rec_get_converted_size(dummy_index, entry, 0);
 
@@ -2158,21 +2217,15 @@ ibuf_add_free_page(void)
 		mtr_commit(&mtr);
 
 		return(FALSE);
-	}
-
-	{
-		buf_block_t*	block;
-
-		block = buf_page_get(
+	} else {
+		buf_block_t*	block = buf_page_get(
 			IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
-
 		buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
 
-
 		page = buf_block_get_frame(block);
 	}
 
-	ibuf_enter();
+	ibuf_enter(&mtr);
 
 	mutex_enter(&ibuf_mutex);
 
@@ -2200,9 +2253,7 @@ ibuf_add_free_page(void)
 	ibuf_bitmap_page_set_bits(
 		bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
 
-	mtr_commit(&mtr);
-
-	ibuf_exit();
+	ibuf_mtr_commit(&mtr);
 
 	return(TRUE);
 }
@@ -2234,7 +2285,7 @@ ibuf_remove_free_page(void)
 	header_page = ibuf_header_page_get(&mtr);
 
 	/* Prevent pessimistic inserts to insert buffer trees for a while */
-	ibuf_enter();
+	ibuf_enter(&mtr);
 	mutex_enter(&ibuf_pessimistic_insert_mutex);
 	mutex_enter(&ibuf_mutex);
 
@@ -2243,14 +2294,12 @@ ibuf_remove_free_page(void)
 		mutex_exit(&ibuf_mutex);
 		mutex_exit(&ibuf_pessimistic_insert_mutex);
 
-		ibuf_exit();
-
-		mtr_commit(&mtr);
+		ibuf_mtr_commit(&mtr);
 
 		return;
 	}
 
-	mtr_start(&mtr2);
+	ibuf_mtr_start(&mtr2);
 
 	root = ibuf_tree_root_get(&mtr2);
 
@@ -2263,9 +2312,8 @@ ibuf_remove_free_page(void)
 	because in fseg_free_page we access level 1 pages, and the root
 	is a level 2 page. */
 
-	mtr_commit(&mtr2);
-
-	ibuf_exit();
+	ibuf_mtr_commit(&mtr2);
+	ibuf_exit(&mtr);
 
 	/* Since pessimistic inserts were prevented, we know that the
 	page is still in the free list. NOTE that also deletes may take
@@ -2280,7 +2328,7 @@ ibuf_remove_free_page(void)
 	buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
 #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
 
-	ibuf_enter();
+	ibuf_enter(&mtr);
 
 	mutex_enter(&ibuf_mutex);
 
@@ -2325,9 +2373,7 @@ ibuf_remove_free_page(void)
 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
 	buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
 #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
-	mtr_commit(&mtr);
-
-	ibuf_exit();
+	ibuf_mtr_commit(&mtr);
 }
 
 /***********************************************************************//**
@@ -2349,8 +2395,6 @@ ibuf_free_excess_pages(void)
 	ut_ad(rw_lock_get_x_lock_count(
 		fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1);
 
-	ut_ad(!ibuf_inside());
-
 	/* NOTE: We require that the thread did not own the latch before,
 	because then we know that we can obey the correct latching order
 	for ibuf latches */
@@ -2381,20 +2425,30 @@ ibuf_free_excess_pages(void)
 	}
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
+	ibuf_get_merge_page_nos_func(contract,rec,mtr,ids,vers,pages,n_stored)
+#else /* UNIV_DEBUG */
+# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
+	ibuf_get_merge_page_nos_func(contract,rec,ids,vers,pages,n_stored)
+#endif /* UNIV_DEBUG */
+
 /*********************************************************************//**
 Reads page numbers from a leaf in an ibuf tree.
 @return a lower limit for the combined volume of records which will be
 merged */
 static
 ulint
-ibuf_get_merge_page_nos(
-/*====================*/
+ibuf_get_merge_page_nos_func(
+/*=========================*/
 	ibool		contract,/*!< in: TRUE if this function is called to
 				contract the tree, FALSE if this is called
 				when a single page becomes full and we look
 				if it pays to read also nearby pages */
-	rec_t*		rec,	/*!< in: record from which we read up and down
-				in the chain of records */
+	const rec_t*	rec,	/*!< in: insert buffer record */
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction holding rec */
+#endif /* UNIV_DEBUG */
 	ulint*		space_ids,/*!< in/out: space id's of the pages */
 	ib_int64_t*	space_versions,/*!< in/out: tablespace version
 				timestamps; used to prevent reading in old
@@ -2417,18 +2471,22 @@ ibuf_get_merge_page_nos(
 	ulint	limit;
 	ulint	n_pages;
 
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
+
 	*n_stored = 0;
 
 	limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4);
 
 	if (page_rec_is_supremum(rec)) {
 
-		rec = page_rec_get_prev(rec);
+		rec = page_rec_get_prev_const(rec);
 	}
 
 	if (page_rec_is_infimum(rec)) {
 
-		rec = page_rec_get_next(rec);
+		rec = page_rec_get_next_const(rec);
 	}
 
 	if (page_rec_is_supremum(rec)) {
@@ -2436,8 +2494,8 @@ ibuf_get_merge_page_nos(
 		return(0);
 	}
 
-	first_page_no = ibuf_rec_get_page_no(rec);
-	first_space_id = ibuf_rec_get_space(rec);
+	first_page_no = ibuf_rec_get_page_no(mtr, rec);
+	first_space_id = ibuf_rec_get_space(mtr, rec);
 	n_pages = 0;
 	prev_page_no = 0;
 	prev_space_id = 0;
@@ -2448,8 +2506,8 @@ ibuf_get_merge_page_nos(
 
 	while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
 
-		rec_page_no = ibuf_rec_get_page_no(rec);
-		rec_space_id = ibuf_rec_get_space(rec);
+		rec_page_no = ibuf_rec_get_page_no(mtr, rec);
+		rec_space_id = ibuf_rec_get_space(mtr, rec);
 
 		if (rec_space_id != first_space_id
 		    || (rec_page_no / IBUF_MERGE_AREA)
@@ -2466,10 +2524,10 @@ ibuf_get_merge_page_nos(
 		prev_page_no = rec_page_no;
 		prev_space_id = rec_space_id;
 
-		rec = page_rec_get_prev(rec);
+		rec = page_rec_get_prev_const(rec);
 	}
 
-	rec = page_rec_get_next(rec);
+	rec = page_rec_get_next_const(rec);
 
 	/* At the loop start there is no prev page; we mark this with a pair
 	of space id, page no (0, 0) for which there can never be entries in
@@ -2487,8 +2545,8 @@ ibuf_get_merge_page_nos(
 			rec_page_no = 1;
 			rec_space_id = 0;
 		} else {
-			rec_page_no = ibuf_rec_get_page_no(rec);
-			rec_space_id = ibuf_rec_get_space(rec);
+			rec_page_no = ibuf_rec_get_page_no(mtr, rec);
+			rec_space_id = ibuf_rec_get_space(mtr, rec);
 			ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
 		}
 
@@ -2499,9 +2557,9 @@ ibuf_get_merge_page_nos(
 		     || rec_page_no != prev_page_no)
 		    && (prev_space_id != 0 || prev_page_no != 0)) {
 
-			if ((prev_page_no == first_page_no
-			     && prev_space_id == first_space_id)
-			    || contract
+			if (contract
+			    || (prev_page_no == first_page_no
+				&& prev_space_id == first_space_id)
 			    || (volume_for_page
 				> ((IBUF_MERGE_THRESHOLD - 1)
 				   * 4 * UNIV_PAGE_SIZE
@@ -2534,14 +2592,14 @@ ibuf_get_merge_page_nos(
 			break;
 		}
 
-		rec_volume = ibuf_rec_get_volume(rec);
+		rec_volume = ibuf_rec_get_volume(mtr, rec);
 
 		volume_for_page += rec_volume;
 
 		prev_page_no = rec_page_no;
 		prev_space_id = rec_space_id;
 
-		rec = page_rec_get_next(rec);
+		rec = page_rec_get_next_const(rec);
 	}
 
 #ifdef UNIV_IBUF_DEBUG
@@ -2576,7 +2634,6 @@ ibuf_contract_ext(
 	mtr_t		mtr;
 
 	*n_pages = 0;
-	ut_ad(!ibuf_inside());
 
 	/* We perform a dirty read of ibuf->empty, without latching
 	the insert buffer root page. We trust this dirty read except
@@ -2588,9 +2645,7 @@ ibuf_contract_ext(
 		return(0);
 	}
 
-	mtr_start(&mtr);
-
-	ibuf_enter();
+	ibuf_mtr_start(&mtr);
 
 	/* Open a cursor to a randomly chosen leaf of the tree, at a random
 	position within the leaf */
@@ -2609,24 +2664,21 @@ ibuf_contract_ext(
 		ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
 		      == FSP_IBUF_TREE_ROOT_PAGE_NO);
 
-		ibuf_exit();
-
-		mtr_commit(&mtr);
+		ibuf_mtr_commit(&mtr);
 		btr_pcur_close(&pcur);
 
 		return(0);
 	}
 
-	sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
+	sum_sizes = ibuf_get_merge_page_nos(TRUE,
+					    btr_pcur_get_rec(&pcur), &mtr,
 					    space_ids, space_versions,
 					    page_nos, n_pages);
 #if 0 /* defined UNIV_IBUF_DEBUG */
 	fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
 		sync, *n_pages, sum_sizes);
 #endif
-	ibuf_exit();
-
-	mtr_commit(&mtr);
+	ibuf_mtr_commit(&mtr);
 	btr_pcur_close(&pcur);
 
 	buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
@@ -2766,6 +2818,13 @@ ibuf_get_volume_buffered_hash(
 	return(TRUE);
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs)	\
+	ibuf_get_volume_buffered_count_func(mtr,rec,hash,size,n_recs)
+#else /* UNIV_DEBUG */
+# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs)	\
+	ibuf_get_volume_buffered_count_func(rec,hash,size,n_recs)
+#endif
 /*********************************************************************//**
 Update the estimate of the number of records on a page, and
 get the space taken by merging the buffered record to the index page.
@@ -2773,8 +2832,11 @@ get the space taken by merging the buffe
 taken in the page directory */
 static
 ulint
-ibuf_get_volume_buffered_count(
-/*===========================*/
+ibuf_get_volume_buffered_count_func(
+/*================================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,	/*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	rec,	/*!< in: insert buffer record */
 	ulint*		hash,	/*!< in/out: hash array */
 	ulint		size,	/*!< in: number of elements in hash array */
@@ -2784,9 +2846,13 @@ ibuf_get_volume_buffered_count(
 	ulint		len;
 	ibuf_op_t	ibuf_op;
 	const byte*	types;
-	ulint		n_fields	= rec_get_n_fields_old(rec);
+	ulint		n_fields;
 
-	ut_ad(ibuf_inside());
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(ibuf_inside(mtr));
+
+	n_fields = rec_get_n_fields_old(rec);
 	ut_ad(n_fields > 4);
 	n_fields -= 4;
 
@@ -2871,7 +2937,7 @@ get_volume_comp:
 		mem_heap_t*	heap = mem_heap_create(500);
 
 		entry = ibuf_build_entry_from_ibuf_rec(
-			rec, heap, &dummy_index);
+			mtr, rec, heap, &dummy_index);
 
 		volume = rec_get_converted_size(dummy_index, entry, 0);
 
@@ -2892,7 +2958,7 @@ static
 ulint
 ibuf_get_volume_buffered(
 /*=====================*/
-	btr_pcur_t*	pcur,	/*!< in: pcur positioned at a place in an
+	const btr_pcur_t*pcur,	/*!< in: pcur positioned at a place in an
 				insert buffer tree where we would insert an
 				entry for the index page whose number is
 				page_no, latch mode has to be BTR_MODIFY_PREV
@@ -2902,16 +2968,17 @@ ibuf_get_volume_buffered(
 	lint*		n_recs,	/*!< in/out: minimum number of records on the
 				page after the buffered changes have been
 				applied, or NULL to disable the counting */
-	mtr_t*		mtr)	/*!< in: mtr */
+	mtr_t*		mtr)	/*!< in: mini-transaction of pcur */
 {
-	ulint	volume;
-	rec_t*	rec;
-	page_t*	page;
-	ulint	prev_page_no;
-	page_t*	prev_page;
-	ulint	next_page_no;
-	page_t*	next_page;
-	ulint	hash_bitmap[128 / sizeof(ulint)]; /* bitmap of buffered recs */
+	ulint		volume;
+	const rec_t*	rec;
+	const page_t*	page;
+	ulint		prev_page_no;
+	const page_t*	prev_page;
+	ulint		next_page_no;
+	const page_t*	next_page;
+	/* bitmap of buffered recs */
+	ulint		hash_bitmap[128 / sizeof(ulint)];
 
 	ut_a(trx_sys_multiple_tablespace_format);
 
@@ -2932,26 +2999,22 @@ ibuf_get_volume_buffered(
 	ut_ad(page_validate(page, ibuf->index));
 
 	if (page_rec_is_supremum(rec)) {
-		rec = page_rec_get_prev(rec);
+		rec = page_rec_get_prev_const(rec);
 	}
 
-	for (;;) {
-		if (page_rec_is_infimum(rec)) {
-
-			break;
-		}
+	for (; !page_rec_is_infimum(rec);
+	     rec = page_rec_get_prev_const(rec)) {
+		ut_ad(page_align(rec) == page);
 
-		if (page_no != ibuf_rec_get_page_no(rec)
-		    || space != ibuf_rec_get_space(rec)) {
+		if (page_no != ibuf_rec_get_page_no(mtr, rec)
+		    || space != ibuf_rec_get_space(mtr, rec)) {
 
 			goto count_later;
 		}
 
 		volume += ibuf_get_volume_buffered_count(
-			rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
-		rec = page_rec_get_prev(rec);
-		ut_ad(page_align(rec) == page);
+			mtr, rec,
+			hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
 	}
 
 	/* Look at the previous page */
@@ -2967,7 +3030,8 @@ ibuf_get_volume_buffered(
 		buf_block_t*	block;
 
 		block = buf_page_get(
-			IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
+			IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
+			mtr);
 
 		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
 
@@ -2977,14 +3041,15 @@ ibuf_get_volume_buffered(
 	}
 
 #ifdef UNIV_BTR_DEBUG
-	ut_a(btr_page_get_next(prev_page, mtr)
-	     == page_get_page_no(page));
+	ut_a(btr_page_get_next(prev_page, mtr) == page_get_page_no(page));
 #endif /* UNIV_BTR_DEBUG */
 
 	rec = page_get_supremum_rec(prev_page);
-	rec = page_rec_get_prev(rec);
+	rec = page_rec_get_prev_const(rec);
+
+	for (;; rec = page_rec_get_prev_const(rec)) {
+		ut_ad(page_align(rec) == prev_page);
 
-	for (;;) {
 		if (page_rec_is_infimum(rec)) {
 
 			/* We cannot go to yet a previous page, because we
@@ -2994,42 +3059,35 @@ ibuf_get_volume_buffered(
 			return(UNIV_PAGE_SIZE);
 		}
 
-		if (page_no != ibuf_rec_get_page_no(rec)
-		    || space != ibuf_rec_get_space(rec)) {
+		if (page_no != ibuf_rec_get_page_no(mtr, rec)
+		    || space != ibuf_rec_get_space(mtr, rec)) {
 
 			goto count_later;
 		}
 
 		volume += ibuf_get_volume_buffered_count(
-			rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
-		rec = page_rec_get_prev(rec);
-		ut_ad(page_align(rec) == prev_page);
+			mtr, rec,
+			hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
 	}
 
 count_later:
 	rec = btr_pcur_get_rec(pcur);
 
 	if (!page_rec_is_supremum(rec)) {
-		rec = page_rec_get_next(rec);
+		rec = page_rec_get_next_const(rec);
 	}
 
-	for (;;) {
-		if (page_rec_is_supremum(rec)) {
-
-			break;
-		}
-
-		if (page_no != ibuf_rec_get_page_no(rec)
-		    || space != ibuf_rec_get_space(rec)) {
+	for (; !page_rec_is_supremum(rec);
+	     rec = page_rec_get_next_const(rec)) {
+		if (page_no != ibuf_rec_get_page_no(mtr, rec)
+		    || space != ibuf_rec_get_space(mtr, rec)) {
 
 			return(volume);
 		}
 
 		volume += ibuf_get_volume_buffered_count(
-			rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
-		rec = page_rec_get_next(rec);
+			mtr, rec,
+			hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
 	}
 
 	/* Look at the next page */
@@ -3045,7 +3103,8 @@ count_later:
 		buf_block_t*	block;
 
 		block = buf_page_get(
-			IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
+			IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
+			mtr);
 
 		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
 
@@ -3059,9 +3118,11 @@ count_later:
 #endif /* UNIV_BTR_DEBUG */
 
 	rec = page_get_infimum_rec(next_page);
-	rec = page_rec_get_next(rec);
+	rec = page_rec_get_next_const(rec);
+
+	for (;; rec = page_rec_get_next_const(rec)) {
+		ut_ad(page_align(rec) == next_page);
 
-	for (;;) {
 		if (page_rec_is_supremum(rec)) {
 
 			/* We give up */
@@ -3069,17 +3130,15 @@ count_later:
 			return(UNIV_PAGE_SIZE);
 		}
 
-		if (page_no != ibuf_rec_get_page_no(rec)
-		    || space != ibuf_rec_get_space(rec)) {
+		if (page_no != ibuf_rec_get_page_no(mtr, rec)
+		    || space != ibuf_rec_get_space(mtr, rec)) {
 
 			return(volume);
 		}
 
 		volume += ibuf_get_volume_buffered_count(
-			rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
-		rec = page_rec_get_next(rec);
-		ut_ad(page_align(rec) == next_page);
+			mtr, rec,
+			hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
 	}
 }
 
@@ -3100,9 +3159,7 @@ ibuf_update_max_tablespace_id(void)
 
 	ut_a(!dict_table_is_comp(ibuf->index->table));
 
-	ibuf_enter();
-
-	mtr_start(&mtr);
+	ibuf_mtr_start(&mtr);
 
 	btr_pcur_open_at_index_side(
 		FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
@@ -3125,14 +3182,20 @@ ibuf_update_max_tablespace_id(void)
 		max_space_id = mach_read_from_4(field);
 	}
 
-	mtr_commit(&mtr);
-	ibuf_exit();
+	ibuf_mtr_commit(&mtr);
 
 	/* printf("Maximum space id in insert buffer %lu\n", max_space_id); */
 
 	fil_set_max_space_id_if_bigger(max_space_id);
 }
 
+#ifdef UNIV_DEBUG
+# define ibuf_get_entry_counter_low(mtr,rec,space,page_no)	\
+	ibuf_get_entry_counter_low_func(mtr,rec,space,page_no)
+#else /* UNIV_DEBUG */
+# define ibuf_get_entry_counter_low(mtr,rec,space,page_no)	\
+	ibuf_get_entry_counter_low_func(rec,space,page_no)
+#endif
 /****************************************************************//**
 Helper function for ibuf_set_entry_counter. Checks if rec is for (space,
 page_no), and if so, reads counter value from it and returns that + 1.
@@ -3140,8 +3203,11 @@ Otherwise, returns 0.
 @return	new counter value, or 0 */
 static
 ulint
-ibuf_get_entry_counter_low(
-/*=======================*/
+ibuf_get_entry_counter_low_func(
+/*============================*/
+#ifdef UNIV_DEBUG
+	mtr_t*		mtr,		/*!< in: mini-transaction of rec */
+#endif /* UNIV_DEBUG */
 	const rec_t*	rec,		/*!< in: insert buffer record */
 	ulint		space,		/*!< in: space id */
 	ulint		page_no)	/*!< in: page number */
@@ -3150,7 +3216,9 @@ ibuf_get_entry_counter_low(
 	const byte*	field;
 	ulint		len;
 
-	ut_ad(ibuf_inside());
+	ut_ad(ibuf_inside(mtr));
+	ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+	      || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
 	ut_ad(rec_get_n_fields_old(rec) > 2);
 
 	field = rec_get_nth_field_old(rec, 1, &len);
@@ -3222,12 +3290,15 @@ ibuf_set_entry_counter(
 	ulint		counter = 0;
 
 	/* pcur points to either a user rec or to a page's infimum record. */
+	ut_ad(ibuf_inside(mtr));
+	ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur),
+				MTR_MEMO_PAGE_X_FIX));
 	ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
 
 	if (btr_pcur_is_on_user_rec(pcur)) {
 
 		counter = ibuf_get_entry_counter_low(
-			btr_pcur_get_rec(pcur), space, page_no);
+			mtr, btr_pcur_get_rec(pcur), space, page_no);
 
 		if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
 			/* The record lacks a counter field.
@@ -3283,7 +3354,7 @@ ibuf_set_entry_counter(
 			ut_ad(page_rec_is_user_rec(rec));
 
 			counter = ibuf_get_entry_counter_low(
-				rec, space, page_no);
+				mtr, rec, space, page_no);
 
 			if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
 				/* The record lacks a counter field.
@@ -3435,7 +3506,6 @@ ibuf_insert_low(
 
 	if (mode == BTR_MODIFY_TREE) {
 		for (;;) {
-			ibuf_enter();
 			mutex_enter(&ibuf_pessimistic_insert_mutex);
 			mutex_enter(&ibuf_mutex);
 
@@ -3446,7 +3516,6 @@ ibuf_insert_low(
 
 			mutex_exit(&ibuf_mutex);
 			mutex_exit(&ibuf_pessimistic_insert_mutex);
-			ibuf_exit();
 
 			if (UNIV_UNLIKELY(!ibuf_add_free_page())) {
 
@@ -3454,11 +3523,9 @@ ibuf_insert_low(
 				return(DB_STRONG_FAIL);
 			}
 		}
-	} else {
-		ibuf_enter();
 	}
 
-	mtr_start(&mtr);
+	ibuf_mtr_start(&mtr);
 
 	btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
 	ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
@@ -3513,7 +3580,7 @@ fail_exit:
 #ifdef UNIV_IBUF_COUNT_DEBUG
 	ut_a((buffered == 0) || ibuf_count_get(space, page_no));
 #endif
-	mtr_start(&bitmap_mtr);
+	ibuf_mtr_start(&bitmap_mtr);
 
 	bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
 					       zip_size, &bitmap_mtr);
@@ -3534,15 +3601,15 @@ fail_exit:
 		if (buffered + entry_size + page_dir_calc_reserved_space(1)
 		    > ibuf_index_page_calc_free_from_bits(zip_size, bits)) {
 			/* Release the bitmap page latch early. */
-			mtr_commit(&bitmap_mtr);
+			ibuf_mtr_commit(&bitmap_mtr);
 
 			/* It may not fit */
 			do_merge = TRUE;
 
-			ibuf_get_merge_page_nos(
-				FALSE, btr_pcur_get_rec(&pcur),
-				space_ids, space_versions,
-				page_nos, &n_stored);
+			ibuf_get_merge_page_nos(FALSE,
+						btr_pcur_get_rec(&pcur), &mtr,
+						space_ids, space_versions,
+						page_nos, &n_stored);
 
 			goto fail_exit;
 		}
@@ -3555,7 +3622,7 @@ fail_exit:
 	    && !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
 				       mode == BTR_MODIFY_PREV, &mtr)) {
 bitmap_fail:
-		mtr_commit(&bitmap_mtr);
+		ibuf_mtr_commit(&bitmap_mtr);
 
 		goto fail_exit;
 	}
@@ -3573,7 +3640,7 @@ bitmap_fail:
 					  &bitmap_mtr);
 	}
 
-	mtr_commit(&bitmap_mtr);
+	ibuf_mtr_commit(&bitmap_mtr);
 
 	cursor = btr_pcur_get_btr_cur(&pcur);
 
@@ -3638,9 +3705,8 @@ func_exit:
 	}
 #endif
 
-	mtr_commit(&mtr);
+	ibuf_mtr_commit(&mtr);
 	btr_pcur_close(&pcur);
-	ibuf_exit();
 
 	mem_heap_free(heap);
 
@@ -3898,7 +3964,7 @@ ibuf_insert_to_index_page(
 	page_t*		page		= buf_block_get_frame(block);
 	rec_t*		rec;
 
-	ut_ad(ibuf_inside());
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(dtuple_check_typed(entry));
 	ut_ad(!buf_block_align(page)->is_hashed);
 
@@ -4045,7 +4111,7 @@ ibuf_set_del_mark(
 	page_cur_t	page_cur;
 	ulint		low_match;
 
-	ut_ad(ibuf_inside());
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(dtuple_check_typed(entry));
 
 	low_match = page_cur_search(
@@ -4102,7 +4168,7 @@ ibuf_delete(
 	page_cur_t	page_cur;
 	ulint		low_match;
 
-	ut_ad(ibuf_inside());
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(dtuple_check_typed(entry));
 
 	low_match = page_cur_search(
@@ -4190,7 +4256,7 @@ ibuf_restore_pos(
 		/* The tablespace has been dropped.  It is possible
 		that another thread has deleted the insert buffer
 		entry.  Do not complain. */
-		btr_pcur_commit_specify_mtr(pcur, mtr);
+		ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
 	} else {
 		fprintf(stderr,
 			"InnoDB: ERROR: Submit the output to"
@@ -4208,7 +4274,7 @@ ibuf_restore_pos(
 			      page_rec_get_next(btr_pcur_get_rec(pcur)));
 		fflush(stderr);
 
-		btr_pcur_commit_specify_mtr(pcur, mtr);
+		ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
 
 		fputs("InnoDB: Validating insert buffer tree:\n", stderr);
 		if (!btr_validate_index(ibuf->index, NULL)) {
@@ -4232,8 +4298,8 @@ ibool
 ibuf_delete_rec(
 /*============*/
 	ulint		space,	/*!< in: space id */
-	ulint		page_no,/*!< in: index page number where the record
-				should belong */
+	ulint		page_no,/*!< in: index page number that the record
+				should belong to */
 	btr_pcur_t*	pcur,	/*!< in: pcur positioned on the record to
 				delete, having latch mode BTR_MODIFY_LEAF */
 	const dtuple_t*	search_tuple,
@@ -4244,10 +4310,10 @@ ibuf_delete_rec(
 	page_t*		root;
 	ulint		err;
 
-	ut_ad(ibuf_inside());
+	ut_ad(ibuf_inside(mtr));
 	ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
-	ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
-	ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
+	ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
+	ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
 
 	success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
 
@@ -4280,22 +4346,22 @@ ibuf_delete_rec(
 	}
 
 	ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
-	ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
-	ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
+	ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
+	ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
 
 	/* We have to resort to a pessimistic delete from ibuf */
 	btr_pcur_store_position(pcur, mtr);
+	ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
 
-	btr_pcur_commit_specify_mtr(pcur, mtr);
-
+	ibuf_mtr_start(mtr);
 	mutex_enter(&ibuf_mutex);
 
-	mtr_start(mtr);
-
 	if (!ibuf_restore_pos(space, page_no, search_tuple,
 			      BTR_MODIFY_TREE, pcur, mtr)) {
 
 		mutex_exit(&ibuf_mutex);
+		ut_ad(!ibuf_inside(mtr));
+		ut_ad(mtr->state == MTR_COMMITTED);
 		goto func_exit;
 	}
 
@@ -4312,9 +4378,11 @@ ibuf_delete_rec(
 	mutex_exit(&ibuf_mutex);
 
 	ibuf->empty = (page_get_n_recs(root) == 0);
-	btr_pcur_commit_specify_mtr(pcur, mtr);
+	ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
 
 func_exit:
+	ut_ad(!ibuf_inside(mtr));
+	ut_ad(mtr->state == MTR_COMMITTED);
 	btr_pcur_close(pcur);
 
 	return(TRUE);
@@ -4406,18 +4474,20 @@ ibuf_merge_or_delete_for_page(
 			update_ibuf_bitmap = FALSE;
 		} else {
 			page_t*	bitmap_page;
+			ulint	bitmap_bits;
 
-			mtr_start(&mtr);
+			ibuf_mtr_start(&mtr);
 
 			bitmap_page = ibuf_bitmap_get_map_page(
 				space, page_no, zip_size, &mtr);
+			bitmap_bits = ibuf_bitmap_page_get_bits(
+				bitmap_page, page_no, zip_size,
+				IBUF_BITMAP_BUFFERED, &mtr);
 
-			if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no,
-						       zip_size,
-						       IBUF_BITMAP_BUFFERED,
-						       &mtr)) {
+			ibuf_mtr_commit(&mtr);
+
+			if (!bitmap_bits) {
 				/* No inserts buffered for this page */
-				mtr_commit(&mtr);
 
 				if (!tablespace_being_deleted) {
 					fil_decr_pending_ibuf_merges(space);
@@ -4425,7 +4495,6 @@ ibuf_merge_or_delete_for_page(
 
 				return;
 			}
-			mtr_commit(&mtr);
 		}
 	} else if (block
 		   && (ibuf_fixed_addr_page(space, zip_size, page_no)
@@ -4434,11 +4503,9 @@ ibuf_merge_or_delete_for_page(
 		return;
 	}
 
-	ibuf_enter();
-
 	heap = mem_heap_create(512);
 
-	if (!trx_sys_multiple_tablespace_format) {
+	if (UNIV_UNLIKELY(!trx_sys_multiple_tablespace_format)) {
 		ut_a(trx_doublewrite_must_reset_space_ids);
 		search_tuple = ibuf_search_tuple_build(space, page_no, heap);
 	} else {
@@ -4465,7 +4532,7 @@ ibuf_merge_or_delete_for_page(
 
 			ut_print_timestamp(stderr);
 
-			mtr_start(&mtr);
+			ibuf_mtr_start(&mtr);
 
 			fputs("  InnoDB: Dump of the ibuf bitmap page:\n",
 			      stderr);
@@ -4473,8 +4540,7 @@ ibuf_merge_or_delete_for_page(
 			bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
 							       zip_size, &mtr);
 			buf_page_print(bitmap_page, 0);
-
-			mtr_commit(&mtr);
+			ibuf_mtr_commit(&mtr);
 
 			fputs("\nInnoDB: Dump of the page:\n", stderr);
 
@@ -4505,7 +4571,7 @@ ibuf_merge_or_delete_for_page(
 	memset(dops, 0, sizeof(dops));
 
 loop:
-	mtr_start(&mtr);
+	ibuf_mtr_start(&mtr);
 
 	if (block) {
 		ibool success;
@@ -4539,8 +4605,8 @@ loop:
 		rec = btr_pcur_get_rec(&pcur);
 
 		/* Check if the entry is for this index page */
-		if (ibuf_rec_get_page_no(rec) != page_no
-		    || ibuf_rec_get_space(rec) != space) {
+		if (ibuf_rec_get_page_no(&mtr, rec) != page_no
+		    || ibuf_rec_get_space(&mtr, rec) != space) {
 
 			if (block) {
 				page_header_reset_last_insert(
@@ -4563,7 +4629,7 @@ loop:
 			dtuple_t*	entry;
 			trx_id_t	max_trx_id;
 			dict_index_t*	dummy_index;
-			ibuf_op_t	op = ibuf_rec_get_op_type(rec);
+			ibuf_op_t	op = ibuf_rec_get_op_type(&mtr, rec);
 
 			max_trx_id = page_get_max_trx_id(page_align(rec));
 			page_update_max_trx_id(block, page_zip, max_trx_id,
@@ -4572,7 +4638,7 @@ loop:
 			ut_ad(page_validate(page_align(rec), ibuf->index));
 
 			entry = ibuf_build_entry_from_ibuf_rec(
-				rec, heap, &dummy_index);
+				&mtr, rec, heap, &dummy_index);
 
 			ut_ad(page_validate(block->frame, dummy_index));
 
@@ -4605,13 +4671,14 @@ loop:
 				Store and restore the cursor position. */
 				ut_ad(rec == btr_pcur_get_rec(&pcur));
 				ut_ad(page_rec_is_user_rec(rec));
-				ut_ad(ibuf_rec_get_page_no(rec) == page_no);
-				ut_ad(ibuf_rec_get_space(rec) == space);
+				ut_ad(ibuf_rec_get_page_no(&mtr, rec)
+				      == page_no);
+				ut_ad(ibuf_rec_get_space(&mtr, rec) == space);
 
 				btr_pcur_store_position(&pcur, &mtr);
-				btr_pcur_commit_specify_mtr(&pcur, &mtr);
+				ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr);
 
-				mtr_start(&mtr);
+				ibuf_mtr_start(&mtr);
 
 				success = buf_page_get_known_nowait(
 					RW_X_LATCH, block,
@@ -4626,7 +4693,8 @@ loop:
 						      BTR_MODIFY_LEAF,
 						      &pcur, &mtr)) {
 
-					mtr_commit(&mtr);
+					ut_ad(!ibuf_inside(&mtr));
+					ut_ad(mtr.state == MTR_COMMITTED);
 					mops[op]++;
 					ibuf_dummy_index_free(dummy_index);
 					goto loop;
@@ -4641,7 +4709,7 @@ loop:
 
 			ibuf_dummy_index_free(dummy_index);
 		} else {
-			dops[ibuf_rec_get_op_type(rec)]++;
+			dops[ibuf_rec_get_op_type(&mtr, rec)]++;
 		}
 
 		/* Delete the record from ibuf */
@@ -4652,7 +4720,7 @@ loop:
 
 			goto loop;
 		} else if (btr_pcur_is_after_last_on_page(&pcur)) {
-			mtr_commit(&mtr);
+			ibuf_mtr_commit(&mtr);
 			btr_pcur_close(&pcur);
 
 			goto loop;
@@ -4686,7 +4754,7 @@ reset_bit:
 		}
 	}
 
-	mtr_commit(&mtr);
+	ibuf_mtr_commit(&mtr);
 	btr_pcur_close(&pcur);
 	mem_heap_free(heap);
 
@@ -4710,8 +4778,6 @@ reset_bit:
 		fil_decr_pending_ibuf_merges(space);
 	}
 
-	ibuf_exit();
-
 #ifdef UNIV_IBUF_COUNT_DEBUG
 	ut_a(ibuf_count_get(space, page_no) == 0);
 #endif
@@ -4731,9 +4797,8 @@ ibuf_delete_for_discarded_space(
 	mem_heap_t*	heap;
 	btr_pcur_t	pcur;
 	dtuple_t*	search_tuple;
-	rec_t*		ibuf_rec;
+	const rec_t*	ibuf_rec;
 	ulint		page_no;
-	ibool		closed;
 	mtr_t		mtr;
 
 	/* Counts for discarded operations. */
@@ -4748,9 +4813,7 @@ ibuf_delete_for_discarded_space(
 
 	memset(dops, 0, sizeof(dops));
 loop:
-	ibuf_enter();
-
-	mtr_start(&mtr);
+	ibuf_mtr_start(&mtr);
 
 	/* Position pcur in the insert buffer at the first entry for the
 	space */
@@ -4770,39 +4833,34 @@ loop:
 		ibuf_rec = btr_pcur_get_rec(&pcur);
 
 		/* Check if the entry is for this space */
-		if (ibuf_rec_get_space(ibuf_rec) != space) {
+		if (ibuf_rec_get_space(&mtr, ibuf_rec) != space) {
 
 			goto leave_loop;
 		}
 
-		page_no = ibuf_rec_get_page_no(ibuf_rec);
+		page_no = ibuf_rec_get_page_no(&mtr, ibuf_rec);
 
-		dops[ibuf_rec_get_op_type(ibuf_rec)]++;
+		dops[ibuf_rec_get_op_type(&mtr, ibuf_rec)]++;
 
 		/* Delete the record from ibuf */
-		closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple,
-					 &mtr);
-		if (closed) {
+		if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
+				    &mtr)) {
 			/* Deletion was pessimistic and mtr was committed:
 			we start from the beginning again */
 
-			ibuf_exit();
-
 			goto loop;
 		}
 
 		if (btr_pcur_is_after_last_on_page(&pcur)) {
-			mtr_commit(&mtr);
+			ibuf_mtr_commit(&mtr);
 			btr_pcur_close(&pcur);
 
-			ibuf_exit();
-
 			goto loop;
 		}
 	}
 
 leave_loop:
-	mtr_commit(&mtr);
+	ibuf_mtr_commit(&mtr);
 	btr_pcur_close(&pcur);
 
 #ifdef HAVE_ATOMIC_BUILTINS
@@ -4814,8 +4872,6 @@ leave_loop:
 	mutex_exit(&ibuf_mutex);
 #endif /* HAVE_ATOMIC_BUILTINS */
 
-	ibuf_exit();
-
 	mem_heap_free(heap);
 }
 
@@ -4831,18 +4887,15 @@ ibuf_is_empty(void)
 	const page_t*	root;
 	mtr_t		mtr;
 
-	ibuf_enter();
-	mtr_start(&mtr);
+	ibuf_mtr_start(&mtr);
 
 	mutex_enter(&ibuf_mutex);
 	root = ibuf_tree_root_get(&mtr);
 	mutex_exit(&ibuf_mutex);
 
 	is_empty = (page_get_n_recs(root) == 0);
-	mtr_commit(&mtr);
-	ibuf_exit();
-
 	ut_a(is_empty == ibuf->empty);
+	ibuf_mtr_commit(&mtr);
 
 	return(is_empty);
 }

=== modified file 'storage/innobase/include/buf0rea.h'
--- a/storage/innobase/include/buf0rea.h	revid:marko.makela@stripped02qg3tzvim8
+++ b/storage/innobase/include/buf0rea.h	revid:marko.makela@stripped
@@ -70,10 +70,10 @@ UNIV_INTERN
 ulint
 buf_read_ahead_linear(
 /*==================*/
-	ulint	space,	/*!< in: space id */
-	ulint	zip_size,/*!< in: compressed page size in bytes, or 0 */
-	ulint	offset);/*!< in: page number of a page; NOTE: the current thread
-			must want access to this page (see NOTE 3 above) */
+	ulint	space,		/*!< in: space id */
+	ulint	zip_size,	/*!< in: compressed page size in bytes, or 0 */
+	ulint	offset,		/*!< in: page number; see NOTE 3 above */
+	ibool	inside_ibuf);	/*!< in: TRUE if we are inside ibuf routine */
 /********************************************************************//**
 Issues read requests for pages which the ibuf module wants to read in, in
 order to contract the insert buffer tree. Technically, this function is like

=== modified file 'storage/innobase/include/ibuf0ibuf.h'
--- a/storage/innobase/include/ibuf0ibuf.h	revid:marko.makela@stripped0322113916-oricw02qg3tzvim8
+++ b/storage/innobase/include/ibuf0ibuf.h	revid:marko.makela@stripped4-hk1iw529qxj6lveq
@@ -104,6 +104,22 @@ UNIV_INTERN
 void
 ibuf_update_max_tablespace_id(void);
 /*===============================*/
+/***************************************************************//**
+Starts an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_start(
+/*===========*/
+	mtr_t*	mtr)	/*!< out: mini-transaction */
+	__attribute__((nonnull));
+/***************************************************************//**
+Commits an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_commit(
+/*============*/
+	mtr_t*	mtr)	/*!< in/out: mini-transaction */
+	__attribute__((nonnull));
 /*********************************************************************//**
 Initializes an ibuf bitmap page. */
 UNIV_INTERN
@@ -224,10 +240,12 @@ routine.
 For instance, a read-ahead of non-ibuf pages is forbidden by threads
 that are executing an insert buffer routine.
 @return TRUE if inside an insert buffer routine */
-UNIV_INTERN
+UNIV_INLINE
 ibool
-ibuf_inside(void);
-/*=============*/
+ibuf_inside(
+/*========*/
+	const mtr_t*	mtr)	/*!< in: mini-transaction */
+	__attribute__((nonnull, pure));
 /***********************************************************************//**
 Checks if a page address is an ibuf bitmap page (level 3 page) address.
 @return	TRUE if a bitmap page */

=== modified file 'storage/innobase/include/ibuf0ibuf.ic'
--- a/storage/innobase/include/ibuf0ibuf.ic	revid:marko.makela@stripped
+++ b/storage/innobase/include/ibuf0ibuf.ic	revid:marko.makela@stripped
@@ -37,6 +37,30 @@ buffer inserts to this page.  If there i
 corresponding bits are set in the ibuf bitmap. */
 #define IBUF_PAGE_SIZE_PER_FREE_SPACE	32
 
+/***************************************************************//**
+Starts an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_start(
+/*===========*/
+	mtr_t*	mtr)	/*!< out: mini-transaction */
+{
+	mtr_start(mtr);
+	mtr->inside_ibuf = TRUE;
+}
+/***************************************************************//**
+Commits an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_commit(
+/*============*/
+	mtr_t*	mtr)	/*!< in/out: mini-transaction */
+{
+	ut_ad(mtr->inside_ibuf);
+	ut_d(mtr->inside_ibuf = FALSE);
+	mtr_commit(mtr);
+}
+
 /** Insert buffer struct */
 struct ibuf_struct{
 	ulint		size;		/*!< current size of the ibuf index
@@ -120,6 +144,22 @@ ibuf_should_try(
 	return(FALSE);
 }
 
+/******************************************************************//**
+Returns TRUE if the current OS thread is performing an insert buffer
+routine.
+
+For instance, a read-ahead of non-ibuf pages is forbidden by threads
+that are executing an insert buffer routine.
+@return TRUE if inside an insert buffer routine */
+UNIV_INLINE
+ibool
+ibuf_inside(
+/*========*/
+	const mtr_t*	mtr)	/*!< in: mini-transaction */
+{
+	return(mtr->inside_ibuf);
+}
+
 /***********************************************************************//**
 Checks if a page address is an ibuf bitmap page address.
 @return	TRUE if a bitmap page */

=== modified file 'storage/innobase/include/mtr0mtr.h'
--- a/storage/innobase/include/mtr0mtr.h	revid:marko.makela@strippedg3tzvim8
+++ b/storage/innobase/include/mtr0mtr.h	revid:marko.makela@stripped
@@ -190,21 +190,21 @@ functions).  The page number parameter w
 /* @} */
 
 /***************************************************************//**
-Starts a mini-transaction and creates a mini-transaction handle
-and buffer in the memory buffer given by the caller.
-@return	mtr buffer which also acts as the mtr handle */
+Starts a mini-transaction. */
 UNIV_INLINE
-mtr_t*
+void
 mtr_start(
 /*======*/
-	mtr_t*	mtr);	/*!< in: memory buffer for the mtr buffer */
+	mtr_t*	mtr)	/*!< out: mini-transaction */
+	__attribute__((nonnull));
 /***************************************************************//**
 Commits a mini-transaction. */
 UNIV_INTERN
 void
 mtr_commit(
 /*=======*/
-	mtr_t*	mtr);	/*!< in: mini-transaction */
+	mtr_t*	mtr)	/*!< in/out: mini-transaction */
+	__attribute__((nonnull));
 /**********************************************************//**
 Sets and returns a savepoint in mtr.
 @return	savepoint */
@@ -378,6 +378,8 @@ struct mtr_struct{
 #endif
 	dyn_array_t	memo;	/*!< memo stack for locks etc. */
 	dyn_array_t	log;	/*!< mini-transaction log */
+	ibool		inside_ibuf;
+				/*!< TRUE if inside ibuf changes */
 	ibool		modifications;
 				/* TRUE if the mtr made modifications to
 				buffer pool pages */

=== modified file 'storage/innobase/include/mtr0mtr.ic'
--- a/storage/innobase/include/mtr0mtr.ic	revid:marko.makela@stripped2113916-oricw02qg3tzvim8
+++ b/storage/innobase/include/mtr0mtr.ic	revid:marko.makela@stripped1iw529qxj6lveq
@@ -30,26 +30,23 @@ Created 11/26/1995 Heikki Tuuri
 #include "mach0data.h"
 
 /***************************************************************//**
-Starts a mini-transaction and creates a mini-transaction handle
-and a buffer in the memory buffer given by the caller.
-@return	mtr buffer which also acts as the mtr handle */
+Starts a mini-transaction. */
 UNIV_INLINE
-mtr_t*
+void
 mtr_start(
 /*======*/
-	mtr_t*	mtr)	/*!< in: memory buffer for the mtr buffer */
+	mtr_t*	mtr)	/*!< out: mini-transaction */
 {
 	dyn_array_create(&(mtr->memo));
 	dyn_array_create(&(mtr->log));
 
 	mtr->log_mode = MTR_LOG_ALL;
 	mtr->modifications = FALSE;
+	mtr->inside_ibuf = FALSE;
 	mtr->n_log_recs = 0;
 
 	ut_d(mtr->state = MTR_ACTIVE);
 	ut_d(mtr->magic_n = MTR_MAGIC_N);
-
-	return(mtr);
 }
 
 /***************************************************//**

=== modified file 'storage/innobase/include/sync0sync.h'
--- a/storage/innobase/include/sync0sync.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/sync0sync.h	revid:marko.makela@stripped
@@ -110,7 +110,6 @@ extern mysql_pfs_key_t	syn_arr_mutex_key
 extern mysql_pfs_key_t	sync_thread_mutex_key;
 # endif /* UNIV_SYNC_DEBUG */
 extern mysql_pfs_key_t	trx_doublewrite_mutex_key;
-extern mysql_pfs_key_t	thr_local_mutex_key;
 extern mysql_pfs_key_t	trx_undo_mutex_key;
 #endif /* UNIV_PFS_MUTEX */
 

=== removed file 'storage/innobase/include/thr0loc.h'
--- a/storage/innobase/include/thr0loc.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/thr0loc.h	1970-01-01 00:00:00 +0000
@@ -1,74 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/thr0loc.h
-The thread local storage
-
-Created 10/5/1995 Heikki Tuuri
-*******************************************************/
-
-/* This module implements storage private to each thread,
-a capability useful in some situations like storing the
-OS handle to the current thread, or its priority. */
-
-#ifndef thr0loc_h
-#define thr0loc_h
-
-#include "univ.i"
-#include "os0thread.h"
-
-/****************************************************************//**
-Initializes the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_init(void);
-/*================*/
- /****************************************************************//**
-Close the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_close(void);
-/*=================*/
-/*******************************************************************//**
-Creates a local storage struct for the calling new thread. */
-UNIV_INTERN
-void
-thr_local_create(void);
-/*==================*/
-/*******************************************************************//**
-Frees the local storage struct for the specified thread. */
-UNIV_INTERN
-void
-thr_local_free(
-/*===========*/
-	os_thread_id_t	id);	/*!< in: thread id */
-/*******************************************************************//**
-Returns pointer to the 'in_ibuf' field within the current thread local
-storage.
-@return	pointer to the in_ibuf field */
-UNIV_INTERN
-ibool*
-thr_local_get_in_ibuf_field(void);
-/*=============================*/
-
-#ifndef UNIV_NONINL
-#include "thr0loc.ic"
-#endif
-
-#endif

=== removed file 'storage/innobase/include/thr0loc.ic'
--- a/storage/innobase/include/thr0loc.ic	revid:marko.makela@stripped
+++ b/storage/innobase/include/thr0loc.ic	1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/thr0loc.ic
-Thread local storage
-
-Created 10/4/1995 Heikki Tuuri
-*******************************************************/

=== modified file 'storage/innobase/mtr/mtr0mtr.c'
--- a/storage/innobase/mtr/mtr0mtr.c	revid:marko.makela@oracle.com-20110322113916-oricw02qg3tzvim8
+++ b/storage/innobase/mtr/mtr0mtr.c	revid:marko.makela@stripped014-hk1iw529qxj6lveq
@@ -251,6 +251,7 @@ mtr_commit(
 	ut_ad(mtr);
 	ut_ad(mtr->magic_n == MTR_MAGIC_N);
 	ut_ad(mtr->state == MTR_ACTIVE);
+	ut_ad(!mtr->inside_ibuf);
 	ut_d(mtr->state = MTR_COMMITTING);
 
 #ifndef UNIV_HOTBACKUP

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	revid:marko.makela@oracle.com-20110322113916-oricw02qg3tzvim8
+++ b/storage/innobase/srv/srv0srv.c	revid:marko.makela@stripped4120014-hk1iw529qxj6lveq
@@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri
 #include "mem0mem.h"
 #include "mem0pool.h"
 #include "sync0sync.h"
-#include "thr0loc.h"
 #include "que0que.h"
 #include "log0recv.h"
 #include "pars0pars.h"
@@ -1129,7 +1128,6 @@ srv_general_init(void)
 	os_sync_init();
 	sync_init();
 	mem_init(srv_mem_pool_size);
-	thr_local_init();
 }
 
 /*======================= InnoDB Server FIFO queue =======================*/
@@ -3071,8 +3069,6 @@ suspend_thread:
 	main thread goes back to loop. */
 
 	goto loop;
-
-	OS_THREAD_DUMMY_RETURN;	/* Not reached, avoid compiler warning */
 }
 
 /*********************************************************************//**

=== modified file 'storage/innobase/srv/srv0start.c'
--- a/storage/innobase/srv/srv0start.c	revid:marko.makela@oracle.com-20110322113916-oricw02qg3tzvim8
+++ b/storage/innobase/srv/srv0start.c	revid:marko.makela@stripped110324120014-hk1iw529qxj6lveq
@@ -85,7 +85,6 @@ Created 2/16/1996 Heikki Tuuri
 # include "row0row.h"
 # include "row0mysql.h"
 # include "btr0pcur.h"
-# include "thr0loc.h"
 # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
 # include "zlib.h" /* for ZLIB_VERSION */
 
@@ -2210,7 +2209,6 @@ innobase_shutdown_for_mysql(void)
 	ibuf_close();
 	log_shutdown();
 	lock_sys_close();
-	thr_local_close();
 	trx_sys_file_format_close();
 	trx_sys_close();
 

=== removed directory 'storage/innobase/thr'
=== removed file 'storage/innobase/thr/thr0loc.c'
--- a/storage/innobase/thr/thr0loc.c	revid:marko.makela@stripped0110322113916-oricw02qg3tzvim8
+++ b/storage/innobase/thr/thr0loc.c	1970-01-01 00:00:00 +0000
@@ -1,259 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file thr/thr0loc.c
-The thread local storage
-
-Created 10/5/1995 Heikki Tuuri
-*******************************************************/
-
-#include "thr0loc.h"
-#ifdef UNIV_NONINL
-#include "thr0loc.ic"
-#endif
-
-#include "sync0sync.h"
-#include "hash0hash.h"
-#include "mem0mem.h"
-#include "srv0srv.h"
-
-/*
-	IMPLEMENTATION OF THREAD LOCAL STORAGE
-	======================================
-
-The threads sometimes need private data which depends on the thread id.
-This is implemented as a hash table, where the hash value is calculated
-from the thread id, to prepare for a large number of threads. The hash table
-is protected by a mutex. If you need modify the program and put new data to
-the thread local storage, just add it to struct thr_local_struct in the
-header file. */
-
-/** Mutex protecting thr_local_hash */
-static mutex_t		thr_local_mutex;
-
-/** The hash table. The module is not yet initialized when it is NULL. */
-static hash_table_t*	thr_local_hash	= NULL;
-
-/** Thread local data */
-typedef struct thr_local_struct thr_local_t;
-
-#ifdef UNIV_PFS_MUTEX
-/* Key to register the mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t	thr_local_mutex_key;
-#endif /* UNIV_PFS_MUTEX */
-
-/** @brief Thread local data.
-The private data for each thread should be put to
-the structure below and the accessor functions written
-for the field. */
-struct thr_local_struct{
-	os_thread_id_t	id;	/*!< id of the thread which owns this struct */
-	os_thread_t	handle;	/*!< operating system handle to the thread */
-	ibool		in_ibuf;/*!< TRUE if the thread is doing an ibuf
-				operation */
-	hash_node_t	hash;	/*!< hash chain node */
-	ulint		magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
-};
-
-/** The value of thr_local_struct::magic_n */
-#define THR_LOCAL_MAGIC_N	1231234
-
-#ifdef UNIV_DEBUG
-/*******************************************************************//**
-Validates thread local data.
-@return	TRUE if valid */
-static
-ibool
-thr_local_validate(
-/*===============*/
-	const thr_local_t*	local)	/*!< in: data to validate */
-{
-	ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
-	ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
-	return(TRUE);
-}
-#endif /* UNIV_DEBUG */
-
-/*******************************************************************//**
-Returns the local storage struct for a thread.
-@return	local storage */
-static
-thr_local_t*
-thr_local_get(
-/*==========*/
-	os_thread_id_t	id)	/*!< in: thread id of the thread */
-{
-	thr_local_t*	local;
-
-try_again:
-	ut_ad(thr_local_hash);
-	ut_ad(mutex_own(&thr_local_mutex));
-
-	/* Look for the local struct in the hash table */
-
-	local = NULL;
-
-	HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
-		    thr_local_t*, local, ut_ad(thr_local_validate(local)),
-		    os_thread_eq(local->id, id));
-	if (local == NULL) {
-		mutex_exit(&thr_local_mutex);
-
-		thr_local_create();
-
-		mutex_enter(&thr_local_mutex);
-
-		goto try_again;
-	}
-
-	ut_ad(thr_local_validate(local));
-
-	return(local);
-}
-
-/*******************************************************************//**
-Returns pointer to the 'in_ibuf' field within the current thread local
-storage.
-@return	pointer to the in_ibuf field */
-UNIV_INTERN
-ibool*
-thr_local_get_in_ibuf_field(void)
-/*=============================*/
-{
-	thr_local_t*	local;
-
-	mutex_enter(&thr_local_mutex);
-
-	local = thr_local_get(os_thread_get_curr_id());
-
-	mutex_exit(&thr_local_mutex);
-
-	return(&(local->in_ibuf));
-}
-
-/*******************************************************************//**
-Creates a local storage struct for the calling new thread. */
-UNIV_INTERN
-void
-thr_local_create(void)
-/*==================*/
-{
-	thr_local_t*	local;
-
-	if (thr_local_hash == NULL) {
-		thr_local_init();
-	}
-
-	local = mem_alloc(sizeof(thr_local_t));
-
-	local->id = os_thread_get_curr_id();
-	local->handle = os_thread_get_curr();
-	local->magic_n = THR_LOCAL_MAGIC_N;
-	local->in_ibuf = FALSE;
-
-	mutex_enter(&thr_local_mutex);
-
-	HASH_INSERT(thr_local_t, hash, thr_local_hash,
-		    os_thread_pf(os_thread_get_curr_id()),
-		    local);
-
-	mutex_exit(&thr_local_mutex);
-}
-
-/*******************************************************************//**
-Frees the local storage struct for the specified thread. */
-UNIV_INTERN
-void
-thr_local_free(
-/*===========*/
-	os_thread_id_t	id)	/*!< in: thread id */
-{
-	thr_local_t*	local;
-
-	mutex_enter(&thr_local_mutex);
-
-	/* Look for the local struct in the hash table */
-
-	HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
-		    thr_local_t*, local, ut_ad(thr_local_validate(local)),
-		    os_thread_eq(local->id, id));
-	if (local == NULL) {
-		mutex_exit(&thr_local_mutex);
-
-		return;
-	}
-
-	HASH_DELETE(thr_local_t, hash, thr_local_hash,
-		    os_thread_pf(id), local);
-
-	mutex_exit(&thr_local_mutex);
-
-	ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
-	ut_ad(thr_local_validate(local));
-
-	mem_free(local);
-}
-
-/****************************************************************//**
-Initializes the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_init(void)
-/*================*/
-{
-
-	ut_a(thr_local_hash == NULL);
-
-	thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
-
-	mutex_create(thr_local_mutex_key,
-		     &thr_local_mutex, SYNC_THR_LOCAL);
-}
-
-/********************************************************************
-Close the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_close(void)
-/*=================*/
-{
-	ulint		i;
-
-	ut_a(thr_local_hash != NULL);
-
-	/* Free the hash elements. We don't remove them from the table
-	because we are going to destroy the table anyway. */
-	for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
-		thr_local_t*	local;
-
-		local = HASH_GET_FIRST(thr_local_hash, i);
-
-		while (local) {
-			thr_local_t*	prev_local = local;
-
-			local = HASH_GET_NEXT(hash, prev_local);
-			ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
-			ut_ad(thr_local_validate(prev_local));
-			mem_free(prev_local);
-		}
-	}
-
-	hash_table_free(thr_local_hash);
-	thr_local_hash = NULL;
-}

=== modified file 'storage/innobase/trx/trx0trx.c'
--- a/storage/innobase/trx/trx0trx.c	revid:marko.makela@stripped
+++ b/storage/innobase/trx/trx0trx.c	revid:marko.makela@stripped0110324120014-hk1iw529qxj6lveq
@@ -38,7 +38,6 @@ Created 3/26/1996 Heikki Tuuri
 #include "usr0sess.h"
 #include "read0read.h"
 #include "srv0srv.h"
-#include "thr0loc.h"
 #include "btr0sea.h"
 #include "os0proc.h"
 #include "trx0xa.h"

Attachment: [text/bzr-bundle] bzr/marko.makela@oracle.com-20110324120014-hk1iw529qxj6lveq.bundle
Thread
bzr push into mysql-5.5-innodb branch (marko.makela:3350 to 3351)Bug#11766305marko.makela24 Mar