diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-02-12 14:27:12 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-02-12 14:27:12 +0200 |
commit | 8afdfd74f0a72c72cf6dc4b35c4648ff65d88355 (patch) | |
tree | a13f05182b2899b162ff4298b36b796f64ad5448 | |
parent | 760a1ca549d26a9e062d1b9cc8c3d4dfadf08ffb (diff) | |
download | mariadb-git-bb-10.6-MDEV-20612-4.tar.gz |
Amend f98795a8749b8053dca2b742938a8d289c7b515abb-10.6-MDEV-20612-4
We must never release lock_sys.latch while holding any
lock_sys_t::hash_latch. Failure to do that could lead to
memory corruption if the buffer pool is resized between
the time lock_sys.latch is released and the hash_latch is released.
-rw-r--r-- | storage/innobase/include/lock0lock.h | 7 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 6 | ||||
-rw-r--r-- | storage/innobase/lock/lock0prdt.cc | 3 |
3 files changed, 12 insertions, 4 deletions
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 9607d9b42a7..f81d7c65b84 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -898,7 +898,12 @@ struct LockMutexGuard struct LockGuard { LockGuard(lock_sys_t::hash_table &hash, const page_id_t id); - ~LockGuard() { lock_sys.rd_unlock(); latch->release(); } + ~LockGuard() + { + latch->release(); + /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */ + lock_sys.rd_unlock(); + } private: /** The hash bucket */ lock_sys_t::hash_latch *latch; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 30ecc913cc5..2e82efe52c9 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -210,8 +210,9 @@ LockGGuard::~LockGGuard() lock_sys.wr_unlock(); else { - lock_sys.rd_unlock(); latch->release(); + /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */ + lock_sys.rd_unlock(); } } #endif @@ -233,10 +234,11 @@ LockMultiGuard::LockMultiGuard(lock_sys_t::hash_table &hash, LockMultiGuard::~LockMultiGuard() { - lock_sys.rd_unlock(); latch1->release(); if (latch1 != latch2) latch2->release(); + /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */ + lock_sys.rd_unlock(); } /** Pretty-print a table lock. diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc index 13f7b092e9d..cb6dde162ce 100644 --- a/storage/innobase/lock/lock0prdt.cc +++ b/storage/innobase/lock/lock0prdt.cc @@ -932,6 +932,7 @@ void lock_sys_t::prdt_page_free_from_discard(const page_id_t id, bool all) lock_rec_discard(rec_hash, lock); } - rd_unlock(); latch->release(); + /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */ + rd_unlock(); } |