You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
3.8 KiB

MDEV-36234: Add innodb_linux_aio This controls which linux implementation to use for innodb_use_native_aio=ON. innodb_linux_aio=auto is equivalent to innodb_linux_aio=io_uring when it is available, and falling back to innodb_linux_aio=aio when not. Debian packaging is no longer aio exclusive or uring, so for those older Debian or Ubuntu releases, its a remove_uring directive. For more recent releases, add mandatory liburing for consistent packaging. WITH_LIBAIO is now an independent option from WITH_URING. LINUX_NATIVE_AIO preprocessor constant is renamed to HAVE_LIBAIO, analogous to existing HAVE_URING. tpool::is_aio_supported(): A common feature check. is_linux_native_aio_supported(): Remove. This had originally been added in mysql/mysql-server@0da310b69db3a39ba2e6d63ff62ef3c027cd63ff in 2012 to fix an issue where io_submit() on CentOS 5.5 would return EINVAL for a /tmp/#sql*.ibd file associated with CREATE TEMPORARY TABLE. But, starting with commit 2e814d4702d71a04388386a9f591d14a35980bfe InnoDB temporary tables will be written to innodb_temp_data_file_path. The 2012 commit said that the error could occur on "old kernels". Any GNU/Linux distribution that we currently support should be based on a newer Linux kernel; for example, Red Hat Enterprise Linux 7 was released in 2014. tpool::create_linux_aio(): Wraps the Linux implementations: create_libaio() and create_liburing(), each defined in separate compilation units (aio_linux.cc, aio_libaio.cc, aio_liburing.cc). The CMake definitions are simplified using target_sources() and target_compile_definitions(), all available since CMake 2.8.12. With this change, there is no need to include ${CMAKE_SOURCE_DIR}/tpool or add TPOOL_DEFINES flags anymore, target_link_libraries(lib tpool) does all that. This is joint work with Daniel Black and Vladislav Vaintroub.
4 months ago
  1. /* Copyright(C) 2019 MariaDB Corporation.
  2. This program is free software; you can redistribute itand /or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; version 2 of the License.
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License
  10. along with this program; if not, write to the Free Software
  11. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
  12. #include "tpool_structs.h"
  13. #include <algorithm>
  14. #include <assert.h>
  15. #include <condition_variable>
  16. #include <iostream>
  17. #include <limits.h>
  18. #include <mutex>
  19. #include <queue>
  20. #include <stack>
  21. #include <thread>
  22. #include <vector>
  23. #include <tpool.h>
  24. namespace tpool
  25. {
  26. /*
  27. Windows AIO implementation, completion port based.
  28. A single thread collects the completion notification with
  29. GetQueuedCompletionStatus(), and forwards io completion callback
  30. the worker threadpool
  31. */
  32. class tpool_generic_win_aio : public aio
  33. {
  34. /* Thread that does collects completion status from the completion port. */
  35. std::thread m_thread;
  36. /* IOCP Completion port.*/
  37. HANDLE m_completion_port;
  38. /* The worker pool where completion routine is executed, as task. */
  39. thread_pool* m_pool;
  40. public:
  41. tpool_generic_win_aio(thread_pool* pool, int max_io) : m_pool(pool)
  42. {
  43. m_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
  44. m_thread = std::thread(aio_completion_thread_proc, this);
  45. }
  46. /**
  47. Task to be executed in the work pool.
  48. */
  49. static void io_completion_task(void* data)
  50. {
  51. auto cb = (aiocb*)data;
  52. cb->execute_callback();
  53. }
  54. void completion_thread_work()
  55. {
  56. for (;;)
  57. {
  58. DWORD n_bytes;
  59. aiocb* aiocb;
  60. ULONG_PTR key;
  61. if (!GetQueuedCompletionStatus(m_completion_port, &n_bytes, &key,
  62. (LPOVERLAPPED*)& aiocb, INFINITE))
  63. break;
  64. aiocb->m_err = 0;
  65. aiocb->m_ret_len = n_bytes;
  66. if (n_bytes != aiocb->m_len)
  67. {
  68. if (GetOverlappedResult(aiocb->m_fh, aiocb,
  69. (LPDWORD)& aiocb->m_ret_len, FALSE))
  70. {
  71. aiocb->m_err = GetLastError();
  72. }
  73. }
  74. aiocb->m_internal_task.m_func = aiocb->m_callback;
  75. aiocb->m_internal_task.m_arg = aiocb;
  76. aiocb->m_internal_task.m_group = aiocb->m_group;
  77. m_pool->submit_task(&aiocb->m_internal_task);
  78. }
  79. }
  80. static void aio_completion_thread_proc(tpool_generic_win_aio* aio)
  81. {
  82. aio->m_pool->m_worker_init_callback();
  83. aio->completion_thread_work();
  84. aio->m_pool->m_worker_destroy_callback();
  85. }
  86. ~tpool_generic_win_aio()
  87. {
  88. if (m_completion_port)
  89. CloseHandle(m_completion_port);
  90. m_thread.join();
  91. }
  92. int submit_io(aiocb* cb) override
  93. {
  94. memset((OVERLAPPED *)cb, 0, sizeof(OVERLAPPED));
  95. cb->m_internal = this;
  96. ULARGE_INTEGER uli;
  97. uli.QuadPart = cb->m_offset;
  98. cb->Offset = uli.LowPart;
  99. cb->OffsetHigh = uli.HighPart;
  100. BOOL ok;
  101. if (cb->m_opcode == aio_opcode::AIO_PREAD)
  102. ok = ReadFile(cb->m_fh.m_handle, cb->m_buffer, cb->m_len, 0, cb);
  103. else
  104. ok = WriteFile(cb->m_fh.m_handle, cb->m_buffer, cb->m_len, 0, cb);
  105. if (ok || (GetLastError() == ERROR_IO_PENDING))
  106. return 0;
  107. return -1;
  108. }
  109. // Inherited via aio
  110. int bind(native_file_handle& fd) override
  111. {
  112. return CreateIoCompletionPort(fd, m_completion_port, 0, 0) ? 0
  113. : GetLastError();
  114. }
  115. int unbind(const native_file_handle& fd) override { return 0; }
  116. const char *get_implementation() const override { return "completion ports"; }
  117. };
  118. aio* create_win_aio(thread_pool* pool, int max_io)
  119. {
  120. return new tpool_generic_win_aio(pool, max_io);
  121. }
  122. } // namespace tpool