summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-11-13 22:06:50 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-11-13 22:06:50 +0200
commite8f8992801988465ff422197bbf439f69d679e6e (patch)
tree627ba8f95f731d9bb206b182c7115a4950712cfe
parentca331bdcda21173dcb4dd4108bad57ce6ff10650 (diff)
parent749ecedfece22d5bdb27a5f682d430e1aa6ec194 (diff)
downloadmariadb-git-e8f8992801988465ff422197bbf439f69d679e6e.tar.gz
MDEV-24188: Merge 10.4 into 10.5
-rw-r--r--storage/innobase/buf/buf0buf.cc30
-rw-r--r--storage/innobase/include/dyn0buf.h18
-rw-r--r--storage/innobase/include/mtr0mtr.h4
-rw-r--r--storage/innobase/include/sync0rw.h2
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc55
-rw-r--r--storage/innobase/sync/sync0rw.cc2
6 files changed, 81 insertions, 30 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 3bbc499bab5..acd221b8b52 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -3772,18 +3772,29 @@ loop:
ut_ad(0);
break;
case BUF_BLOCK_FILE_PAGE:
- buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+ if (!mtr->have_x_latch(*block))
{
- const auto num_fix_count= mtr->get_fix_count(block) + 1;
- while (block->page.io_fix() != BUF_IO_NONE ||
- num_fix_count != block->page.buf_fix_count())
+ buf_block_buf_fix_inc(block, __FILE__, __LINE__);
{
- mysql_mutex_unlock(&buf_pool.mutex);
- os_thread_yield();
- mysql_mutex_lock(&buf_pool.mutex);
+ while (block->page.io_fix() != BUF_IO_NONE ||
+ block->page.buf_fix_count() != 1)
+ {
+ timespec abstime;
+ set_timespec_nsec(abstime, 1000000);
+ mysql_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex,
+ &abstime);
+ }
}
+ rw_lock_x_lock(&block->lock);
+ mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
+ }
+ else
+ {
+ ut_ad(!block->page.ibuf_exist);
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!block->index);
+#endif
}
- rw_lock_x_lock(&block->lock);
#ifdef BTR_CUR_HASH_ADAPT
drop_hash_entry= block->index;
#endif
@@ -3808,6 +3819,7 @@ loop:
buf_page_free_descriptor(&block->page);
block= free_block;
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+ mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
break;
}
@@ -3818,8 +3830,6 @@ loop:
btr_search_drop_page_hash_index(block);
#endif /* BTR_CUR_HASH_ADAPT */
- mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
-
if (block->page.ibuf_exist)
{
if (!recv_recovery_is_on())
diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h
index e89733fc9ed..cb8b998f0ea 100644
--- a/storage/innobase/include/dyn0buf.h
+++ b/storage/innobase/include/dyn0buf.h
@@ -331,6 +331,24 @@ public:
}
/**
+ Iterate over each block and call the functor.
+ @return false if iteration was terminated. */
+ template <typename Functor>
+ bool for_each_block(const Functor& functor) const
+ {
+ for (typename list_t::iterator it = m_list.begin(),
+ end = m_list.end();
+ it != end; ++it) {
+
+ if (!functor(&*it)) {
+ return false;
+ }
+ }
+
+ return(true);
+ }
+
+ /**
Iterate over all the blocks in reverse and call the iterator
@return false if iteration was terminated. */
template <typename Functor>
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index cf8f37c3fa5..f8ab7cf440f 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -151,6 +151,10 @@ struct mtr_t {
return old_mode;
}
+ /** Check if we are holding a block latch in exclusive mode
+ @param block buffer pool block to search for */
+ bool have_x_latch(const buf_block_t &block) const;
+
/** Copy the tablespaces associated with the mini-transaction
(needed for generating FILE_MODIFY records)
@param[in] mtr mini-transaction that may modify
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index fce598f0930..084acc51d1f 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -506,7 +506,7 @@ the pass value == 0. */
bool
rw_lock_own(
/*========*/
- rw_lock_t* lock, /*!< in: rw-lock */
+ const rw_lock_t*lock, /*!< in: rw-lock */
ulint lock_type) /*!< in: lock type: RW_LOCK_S,
RW_LOCK_X */
MY_ATTRIBUTE((warn_unused_result));
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index dede92ad755..a6f74bf927f 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -893,29 +893,48 @@ inline std::pair<lsn_t,bool> mtr_t::finish_write(ulint len)
return std::make_pair(start_lsn, flush);
}
-/** Find buffer fix count of the given block acquired by the
-mini-transaction */
-struct FindBlock
+/** Find out whether a block was X-latched by the mini-transaction */
+struct FindBlockX
{
- int32_t num_fix;
- const buf_block_t *const block;
+ const buf_block_t &block;
- FindBlock(const buf_block_t *block_buf): num_fix(0), block(block_buf) {}
+ FindBlockX(const buf_block_t &block): block(block) {}
- bool operator()(const mtr_memo_slot_t* slot)
+ /** @return whether the block was not found x-latched */
+ bool operator()(const mtr_memo_slot_t *slot) const
{
- if (slot->object == block)
- num_fix++;
- return true;
+ return slot->object != &block || slot->type == MTR_MEMO_PAGE_X_FIX;
+ }
+};
+
+#ifdef UNIV_DEBUG
+/** Assert that the block is not present in the mini-transaction */
+struct FindNoBlock
+{
+ const buf_block_t &block;
+
+ FindNoBlock(const buf_block_t &block): block(block) {}
+
+ /** @return whether the block was not found */
+ bool operator()(const mtr_memo_slot_t *slot) const
+ {
+ return slot->object != &block;
}
};
+#endif /* UNIV_DEBUG */
-uint32_t mtr_t::get_fix_count(const buf_block_t *block) const
+bool mtr_t::have_x_latch(const buf_block_t &block) const
{
- Iterate<FindBlock> iteration((FindBlock(block)));
- if (m_memo.for_each_block(iteration))
- return iteration.functor.num_fix;
- return 0;
+ if (m_memo.for_each_block(CIterate<FindBlockX>(FindBlockX(block))))
+ {
+ ut_ad(m_memo.for_each_block(CIterate<FindNoBlock>(FindNoBlock(block))));
+ ut_ad(!memo_contains_flagged(&block,
+ MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_SX_FIX |
+ MTR_MEMO_BUF_FIX | MTR_MEMO_MODIFY));
+ return false;
+ }
+ ut_ad(rw_lock_own(&block.lock, RW_LOCK_X));
+ return true;
}
#ifdef UNIV_DEBUG
@@ -931,13 +950,13 @@ bool mtr_t::memo_contains(const rw_lock_t &lock, mtr_memo_type_t type)
switch (type) {
case MTR_MEMO_X_LOCK:
- ut_ad(rw_lock_own(const_cast<rw_lock_t*>(&lock), RW_LOCK_X));
+ ut_ad(rw_lock_own(&lock, RW_LOCK_X));
break;
case MTR_MEMO_SX_LOCK:
- ut_ad(rw_lock_own(const_cast<rw_lock_t*>(&lock), RW_LOCK_SX));
+ ut_ad(rw_lock_own(&lock, RW_LOCK_SX));
break;
case MTR_MEMO_S_LOCK:
- ut_ad(rw_lock_own(const_cast<rw_lock_t*>(&lock), RW_LOCK_S));
+ ut_ad(rw_lock_own(&lock, RW_LOCK_S));
break;
default:
break;
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index b86e11900b8..29a5c6cd036 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -990,7 +990,7 @@ the pass value == 0.
bool
rw_lock_own(
/*========*/
- rw_lock_t* lock, /*!< in: rw-lock */
+ const rw_lock_t*lock, /*!< in: rw-lock */
ulint lock_type) /*!< in: lock type: RW_LOCK_S,
RW_LOCK_X */
{