From c0eeb72526bb4c6656d84b89ced33880ca1639d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com>
Date: Thu, 13 Apr 2023 12:25:41 +0300
Subject: [PATCH 1/2] MDEV-28974 fixup: Fix error and warning messages

fil_name_process(): Starting with
commit 212994f704496d01881f377e34e04bd007e5e298
the name is not guaranteed to be NUL terminated.
---
 storage/innobase/log/log0recv.cc | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 8d05d6a5f14..3b6e3008a95 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1307,7 +1307,8 @@ same_space:
 			} else {
 				ib::error() << "Tablespace " << space_id
 					<< " has been found in two places: '"
-					<< f.name << "' and '" << name << "'."
+					<< f.name << "' and '"
+					<< fname.name << "'."
 					" You must delete one of them.";
 				recv_sys.set_corrupt_fs();
 			}
@@ -1333,7 +1334,8 @@ same_space:
 
 				ib::info()
 					<< "At LSN: " << recv_sys.recovered_lsn
-					<< ": unable to open file " << name
+					<< ": unable to open file "
+					<< fname.name
 					<< " for tablespace " << space_id;
 			}
 			break;
@@ -1350,8 +1352,9 @@ same_space:
 			ut_ad(space == NULL);
 			if (srv_force_recovery == 0) {
 				sql_print_error("InnoDB: Recovery cannot access"
-						" file %s (tablespace "
-						UINT32PF ")", name, space_id);
+						" file %.*s (tablespace "
+						UINT32PF ")", int(len), name,
+						space_id);
 				sql_print_information("InnoDB: You may set "
 						      "innodb_force_recovery=1"
 						      " to ignore this and"
@@ -1362,9 +1365,10 @@ same_space:
 			}
 
 			sql_print_warning("InnoDB: Ignoring changes to"
-					  " file %s (tablespace " UINT32PF ")"
+					  " file %.*s (tablespace "
+					  UINT32PF ")"
 					  " due to innodb_force_recovery",
-					  name, space_id);
+					  int(len), name, space_id);
 		}
 	}
 }

From f50abab195168e497f36715b2f0dbdad8183ed4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com>
Date: Thu, 13 Apr 2023 15:18:26 +0300
Subject: [PATCH 2/2] MDEV-31048 PERFORMANCE_SCHEMA lakcs InnoDB read_slots and
 write_slots

tpool::cache::m_mtx: Add PERFORMANCE_SCHEMA instrumentation
(wait/synch/mutex/innodb/tpool_cache_mutex). This covers the
InnoDB read_slots and write_slots for asynchronous data page I/O.
---
 storage/innobase/handler/ha_innodb.cc |  2 +
 storage/innobase/os/os0file.cc        | 14 +++---
 tpool/tpool_structs.h                 | 64 ++++++++++++++++++---------
 3 files changed, 55 insertions(+), 25 deletions(-)

diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 04a857ecd0c..f102789d7ab 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -542,6 +542,7 @@ mysql_pfs_key_t	trx_pool_manager_mutex_key;
 mysql_pfs_key_t	lock_wait_mutex_key;
 mysql_pfs_key_t	trx_sys_mutex_key;
 mysql_pfs_key_t	srv_threads_mutex_key;
+mysql_pfs_key_t	tpool_cache_mutex_key;
 
 /* all_innodb_mutexes array contains mutexes that are
 performance schema instrumented if "UNIV_PFS_MUTEX"
@@ -577,6 +578,7 @@ static PSI_mutex_info all_innodb_mutexes[] = {
 	PSI_KEY(rtr_match_mutex),
 	PSI_KEY(rtr_path_mutex),
 	PSI_KEY(trx_sys_mutex),
+	PSI_KEY(tpool_cache_mutex),
 };
 # endif /* UNIV_PFS_MUTEX */
 
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 12561877c0c..d366c784b96 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -132,7 +132,7 @@ public:
 		wait();
 	}
 
-	std::mutex& mutex()
+	mysql_mutex_t& mutex()
 	{
 		return m_cache.mutex();
 	}
@@ -3668,8 +3668,10 @@ void os_aio_wait_until_no_pending_writes()
 /** @return number of pending reads */
 size_t os_aio_pending_reads()
 {
-  std::unique_lock<std::mutex> lk(read_slots->mutex());
-  return read_slots->pending_io_count();
+  mysql_mutex_lock(&read_slots->mutex());
+  size_t pending= read_slots->pending_io_count();
+  mysql_mutex_unlock(&read_slots->mutex());
+  return pending;
 }
 
 /** @return approximate number of pending reads */
@@ -3681,8 +3683,10 @@ size_t os_aio_pending_reads_approx()
 /** @return number of pending writes */
 size_t os_aio_pending_writes()
 {
-  std::unique_lock<std::mutex> lk(write_slots->mutex());
-  return write_slots->pending_io_count();
+  mysql_mutex_lock(&write_slots->mutex());
+  size_t pending= write_slots->pending_io_count();
+  mysql_mutex_unlock(&write_slots->mutex());
+  return pending;
 }
 
 /** Wait until all pending asynchronous reads have completed. */
diff --git a/tpool/tpool_structs.h b/tpool/tpool_structs.h
index b6ca3f54016..550a92d6e58 100644
--- a/tpool/tpool_structs.h
+++ b/tpool/tpool_structs.h
@@ -14,14 +14,13 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
 
 #pragma once
+#include <my_global.h>
+#include <my_pthread.h>
 #include <vector>
 #include <stack>
-#include <mutex>
-#include <condition_variable>
 #include <assert.h>
 #include <algorithm>
 
-
 /* Suppress TSAN warnings, that we believe are not critical. */
 #if defined(__has_feature)
 #define TPOOL_HAS_FEATURE(...) __has_feature(__VA_ARGS__)
@@ -37,6 +36,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
 #define TPOOL_SUPPRESS_TSAN
 #endif
 
+#ifdef HAVE_PSI_INTERFACE
+typedef unsigned int mysql_pfs_key_t;
+extern mysql_pfs_key_t tpool_cache_mutex_key;
+#endif
+
 namespace tpool
 {
 
@@ -55,13 +59,13 @@ namespace tpool
 template<typename T> class cache
 {
   /** Protects updates of m_pos and m_cache members */
-  std::mutex m_mtx;
+  mysql_mutex_t m_mtx;
 
   /**
     Notify waiting threads about "cache full" or "cache not empty" conditions
     @see get() and wait()
   */
-  std::condition_variable m_cv;
+  pthread_cond_t m_cv;
 
   /** Cached items vector.Does not change after construction */
   std::vector<T> m_base;
@@ -108,13 +112,22 @@ public:
   Constructor
   @param size - maximum number of items in cache
   */
-  cache(size_t size) : m_mtx(), m_cv(), m_base(size), m_cache(size),
+  cache(size_t size) : m_base(size), m_cache(size),
     m_waiters(), m_pos(0)
   {
+    mysql_mutex_init(tpool_cache_mutex_key, &m_mtx, nullptr);
+    pthread_cond_init(&m_cv, nullptr);
+
     for(size_t i= 0 ; i < size; i++)
       m_cache[i]= &m_base[i];
   }
 
+  ~cache()
+  {
+    mysql_mutex_destroy(&m_mtx);
+    pthread_cond_destroy(&m_cv);
+ }
+
   /**
    Retrieve an item from cache. Waits for free item, if cache is
    currently empty.
@@ -122,16 +135,17 @@ public:
   */
   T* get()
   {
-    std::unique_lock<std::mutex> lk(m_mtx);
-    while(is_empty())
-      m_cv.wait(lk);
+    mysql_mutex_lock(&m_mtx);
+    while (is_empty())
+      my_cond_wait(&m_cv, &m_mtx.m_mutex);
     assert(m_pos < capacity());
     //  return last element
-    return m_cache[m_pos++];
+    T *t= m_cache[m_pos++];
+    mysql_mutex_unlock(&m_mtx);
+    return t;
   }
 
-
-  std::mutex &mutex() { return m_mtx; }
+  mysql_mutex_t &mutex() { return m_mtx; }
 
   /**
    Put back an element to cache.
@@ -139,7 +153,7 @@ public:
   */
   void put(T *ele)
   {
-    std::unique_lock<std::mutex> lk(m_mtx);
+    mysql_mutex_lock(&m_mtx);
     assert(!is_full());
     // put element to the logical end of the array
     m_cache[--m_pos] = ele;
@@ -147,7 +161,8 @@ public:
     /* Notify waiters  when the cache becomes
      not empty, or when it becomes full */
     if (m_pos == 1 || (m_waiters && is_full()))
-      m_cv.notify_all();
+      pthread_cond_broadcast(&m_cv);
+    mysql_mutex_unlock(&m_mtx);
   }
 
   /** Check if pointer represents cached element */
@@ -157,14 +172,23 @@ public:
     return ele >= &m_base[0] && ele <= &m_base[capacity() - 1];
   }
 
-  /** Wait until cache is full.*/
+  /** Wait until cache is full
+  @param m cache mutex (locked) */
+  void wait(mysql_mutex_t &m)
+  {
+    mysql_mutex_assert_owner(&m);
+    m_waiters++;
+    while (!is_full())
+      my_cond_wait(&m_cv, &m.m_mutex);
+    m_waiters--;
+  }
+
+  /* Wait until cache is full.*/
   void wait()
   {
-    std::unique_lock<std::mutex> lk(m_mtx);
-    m_waiters++;
-    while(!is_full())
-      m_cv.wait(lk);
-    m_waiters--;
+    mysql_mutex_lock(&m_mtx);
+    wait(m_mtx);
+    mysql_mutex_unlock(&m_mtx);
   }
 
   /**