diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 3240d655bd3f1ed8db221058e0d7580dd505e33a..24bcbdbb9496f54a39170c81ef45042bb6381ded 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
 
 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
@@ -400,7 +400,7 @@ xdes_get_descriptor_const(
 	page_no_t		offset,
 	mtr_t*			mtr)
 {
-	ut_ad(mtr->memo_contains(*space, true));
+	ut_ad(space->is_owner() || mtr->memo_contains(*space, true));
 	ut_ad(offset < space->free_limit);
 	ut_ad(offset < space->size_in_header);
 
@@ -2563,7 +2563,9 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
 							  page);
 
 	mtr.start();
-	mtr.s_lock_space(space);
+	if (!space->is_owner()) {
+		mtr.s_lock_space(space);
+	}
 
 	if (page >= space->free_limit || page >= space->size_in_header) {
 		is_free = true;
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 36918640fa8ee5f635f8fcec6319b2cafef862d3..717aa6a91a48b32b6e16302885bc8ede656f4947 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2020, MariaDB Corporation.
+Copyright (c) 2016, 2021, MariaDB Corporation.
 
 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
@@ -4109,6 +4109,29 @@ bool ibuf_page_exists(const page_id_t id, ulint zip_size)
 	return bitmap_bits;
 }
 
+/** Reset the bits in the bitmap page for the given block and page id.
+@param b        X-latched secondary index page (nullptr to discard changes)
+@param page_id  page identifier
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param mtr      mini-transaction */
+static void ibuf_reset_bitmap(buf_block_t *b, page_id_t page_id,
+                              ulint zip_size, mtr_t *mtr)
+{
+ buf_block_t *bitmap= ibuf_bitmap_get_map_page(page_id, zip_size, mtr);
+ if (!bitmap)
+   return;
+
+ const ulint physical_size = zip_size ? zip_size : srv_page_size;
+ /* FIXME: update the bitmap byte only once! */
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(bitmap, page_id,
+                                                 physical_size, false, mtr);
+
+ if (b)
+   ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(bitmap, page_id, physical_size,
+                                               ibuf_index_page_calc_free(b),
+                                               mtr);
+}
+
 /** When an index page is read from a disk to the buffer pool, this function
 applies any buffered operations to the page and deletes the entries from the
 insert buffer. If the page is not read, but created in the buffer pool, this
@@ -4170,6 +4193,14 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
 
 		ibuf_mtr_commit(&mtr);
 
+		if (bitmap_bits && fseg_page_is_free(
+				space, page_id.page_no())) {
+			ibuf_mtr_start(&mtr);
+			ibuf_reset_bitmap(block, page_id, zip_size, &mtr);
+			ibuf_mtr_commit(&mtr);
+			bitmap_bits = 0;
+		}
+
 		if (!bitmap_bits) {
 			/* No changes are buffered for this page. */
 			space->release();
@@ -4373,18 +4404,8 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
 	}
 
 reset_bit:
-	if (!space) {
-	} else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page(
-			   page_id, zip_size, &mtr)) {
-		/* FIXME: update the bitmap byte only once! */
-		ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
-			bitmap, page_id, physical_size, false, &mtr);
-
-		if (block != NULL) {
-			ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
-				bitmap, page_id, physical_size,
-				ibuf_index_page_calc_free(block), &mtr);
-		}
+	if (space) {
+		ibuf_reset_bitmap(block, page_id, zip_size, &mtr);
 	}
 
 	ibuf_mtr_commit(&mtr);
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 2fbb2a1764e13bd51f627187a517c2328d61d151..94740c6841088f2ff1db83691fda077a3af3ddd6 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2020, MariaDB Corporation.
+Copyright (c) 2013, 2021, MariaDB Corporation.
 
 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
@@ -398,7 +398,7 @@ struct fil_space_t final
   static constexpr uint32_t PENDING= ~(STOPPING | CLOSING | NEEDS_FSYNC);
   /** latch protecting all page allocation bitmap pages */
   srw_lock latch;
-  ut_d(os_thread_id_t latch_owner;)
+  os_thread_id_t latch_owner;
   ut_d(Atomic_relaxed<uint32_t> latch_count;)
 public:
 	UT_LIST_NODE_T(fil_space_t) named_spaces;
@@ -996,14 +996,14 @@ struct fil_space_t final
 
 #ifdef UNIV_DEBUG
   bool is_latched() const { return latch_count != 0; }
-  bool is_owner() const { return latch_owner == os_thread_get_curr_id(); }
 #endif
+  bool is_owner() const { return latch_owner == os_thread_get_curr_id(); }
   /** Acquire the allocation latch in exclusive mode */
   void x_lock()
   {
     latch.wr_lock(SRW_LOCK_CALL);
     ut_ad(!latch_owner);
-    ut_d(latch_owner= os_thread_get_curr_id());
+    latch_owner= os_thread_get_curr_id();
     ut_ad(!latch_count.fetch_add(1));
   }
   /** Release the allocation latch from exclusive mode */
@@ -1011,12 +1011,13 @@ struct fil_space_t final
   {
     ut_ad(latch_count.fetch_sub(1) == 1);
     ut_ad(latch_owner == os_thread_get_curr_id());
-    ut_d(latch_owner= 0);
+    latch_owner= 0;
     latch.wr_unlock();
   }
   /** Acquire the allocation latch in shared mode */
   void s_lock()
   {
+    ut_ad(!is_owner());
     latch.rd_lock(SRW_LOCK_CALL);
     ut_ad(!latch_owner);
     ut_d(latch_count.fetch_add(1));
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 448a0af3b276023ea1c9f43dd924fbdb232b52a2..3c6cddf87ba1c3397f287a7f7c176575d1909a1d 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -2,7 +2,7 @@
 
 Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2020, MariaDB Corporation.
+Copyright (c) 2013, 2021, MariaDB Corporation.
 
 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
@@ -253,29 +253,29 @@ struct mtr_t {
     memo_push(lock, MTR_MEMO_SX_LOCK);
   }
 
-	/** Acquire a tablespace S-latch.
-	@param[in]	space	tablespace */
-	void s_lock_space(fil_space_t* space)
-	{
-		ut_ad(space->purpose == FIL_TYPE_TEMPORARY
-		      || space->purpose == FIL_TYPE_IMPORT
-		      || space->purpose == FIL_TYPE_TABLESPACE);
-		memo_push(space, MTR_MEMO_SPACE_S_LOCK);
-		space->s_lock();
-	}
+  /** Acquire a tablespace S-latch.
+  @param space  tablespace */
+  void s_lock_space(fil_space_t *space)
+  {
+    ut_ad(space->purpose == FIL_TYPE_TEMPORARY ||
+          space->purpose == FIL_TYPE_IMPORT ||
+          space->purpose == FIL_TYPE_TABLESPACE);
+    memo_push(space, MTR_MEMO_SPACE_S_LOCK);
+    space->s_lock();
+  }
 
-	/** Acquire a tablespace X-latch.
-	@param[in]	space	tablespace */
-	void x_lock_space(fil_space_t* space);
-	/** Release an object in the memo stack.
-	@param object	object
-	@param type	object type
-	@return bool if lock released */
-	bool memo_release(const void* object, ulint type);
-	/** Release a page latch.
-	@param[in]	ptr	pointer to within a page frame
-	@param[in]	type	object type: MTR_MEMO_PAGE_X_FIX, ... */
-	void release_page(const void* ptr, mtr_memo_type_t type);
+  /** Acquire an exclusive tablespace latch.
+  @param space  tablespace */
+  void x_lock_space(fil_space_t *space);
+  /** Release an object in the memo stack.
+  @param object	object
+  @param type	object type
+  @return bool if lock released */
+  bool memo_release(const void *object, ulint type);
+  /** Release a page latch.
+  @param[in]	ptr	pointer to within a page frame
+  @param[in]	type	object type: MTR_MEMO_PAGE_X_FIX, ... */
+  void release_page(const void *ptr, mtr_memo_type_t type);
 
 private:
   /** Note that the mini-transaction will modify data. */
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index 5445dc0a76371396818c46aea72111de8a9f3ece..c09aa644b444fd695a33753abaee2bd2c76bc85b 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
 
 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
@@ -336,9 +336,9 @@ enum mtr_memo_type_t {
 
 	MTR_MEMO_SX_LOCK = RW_SX_LATCH << 5,
 
-	/** rd_lock() on fil_space_t::latch */
-	MTR_MEMO_SPACE_X_LOCK = MTR_MEMO_SX_LOCK << 1,
 	/** wr_lock() on fil_space_t::latch */
+	MTR_MEMO_SPACE_X_LOCK = MTR_MEMO_SX_LOCK << 1,
+	/** rd_lock() on fil_space_t::latch */
 	MTR_MEMO_SPACE_S_LOCK = MTR_MEMO_SX_LOCK << 2
 };
 #endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 7db9494e26f22000d8cb3a48fdbb431132fc1da0..4f80bc0c7a4e9ae78c10b483036c5614438c4288 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
 
 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
@@ -569,8 +569,8 @@ mtr_t::x_lock_space(ulint space_id)
 	return(space);
 }
 
-/** Acquire a tablespace X-latch.
-@param[in]	space	tablespace */
+/** Acquire an exclusive tablespace latch.
+@param space  tablespace */
 void mtr_t::x_lock_space(fil_space_t *space)
 {
   ut_ad(space->purpose == FIL_TYPE_TEMPORARY ||