Skip to content

Commit 5157b6e

Browse files
committed
MDEV-36234: dualstack aio/io_uring add innodb_linux_aio variable
This controls which linux implementation to use under the assumption that innodb_native_aio is true. "auto" select liburing first, if fails, tries libaio with a filesystem test, and if fails, falls back to no-async. "aio" starts is per auto, but skips liburing step.
1 parent 3313a73 commit 5157b6e

13 files changed

+171
-39
lines changed

mysql-test/mariadb-test-run.pl

+1-1
Original file line numberDiff line numberDiff line change
@@ -4522,7 +4522,7 @@ ($$)
45224522
qr|InnoDB: io_setup\(\) attempt|,
45234523
qr|InnoDB: io_setup\(\) failed with EAGAIN|,
45244524
qr|io_uring_queue_init\(\) failed with|,
4525-
qr|InnoDB: liburing disabled|,
4525+
qr|InnoDB: io_uring failed: falling back to libaio|,
45264526
qr/InnoDB: Failed to set O_DIRECT on file/,
45274527
qr|setrlimit could not change the size of core files to 'infinity';|,
45284528
qr|failed to retrieve the MAC address|,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
select @@global.innodb_linux_aio;
2+
@@global.innodb_linux_aio
3+
auto
4+
select @@session.innodb_linux_aio;
5+
ERROR HY000: Variable 'innodb_linux_aio' is a GLOBAL variable
6+
show global variables like 'innodb_linux_aio';
7+
Variable_name Value
8+
innodb_linux_aio auto
9+
show session variables like 'innodb_linux_aio';
10+
Variable_name Value
11+
innodb_linux_aio auto
12+
select * from information_schema.global_variables where variable_name='innodb_linux_aio';
13+
VARIABLE_NAME VARIABLE_VALUE
14+
INNODB_LINUX_AIO auto
15+
select * from information_schema.session_variables where variable_name='innodb_linux_aio';
16+
VARIABLE_NAME VARIABLE_VALUE
17+
INNODB_LINUX_AIO auto
18+
set global innodb_linux_aio='auto';
19+
ERROR HY000: Variable 'innodb_linux_aio' is a read only variable
20+
set session innodb_linux_aio='aio';
21+
ERROR HY000: Variable 'innodb_linux_aio' is a read only variable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--source include/have_innodb.inc
2+
--source include/linux.inc
3+
# enum readonly
4+
5+
#
6+
# show values;
7+
#
8+
select @@global.innodb_linux_aio;
9+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
10+
select @@session.innodb_linux_aio;
11+
show global variables like 'innodb_linux_aio';
12+
show session variables like 'innodb_linux_aio';
13+
select * from information_schema.global_variables where variable_name='innodb_linux_aio';
14+
select * from information_schema.session_variables where variable_name='innodb_linux_aio';
15+
16+
#
17+
# show that it's read-only
18+
#
19+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
20+
set global innodb_linux_aio='auto';
21+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
22+
set session innodb_linux_aio='aio';
23+

mysql-test/suite/sys_vars/t/sysvars_innodb.test

+1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ select VARIABLE_NAME, SESSION_VALUE, DEFAULT_VALUE, VARIABLE_SCOPE, VARIABLE_TYP
1616
'innodb_numa_interleave', # only available WITH_NUMA
1717
'innodb_evict_tables_on_commit_debug', # one may want to override this
1818
'innodb_use_native_aio', # default value depends on OS
19+
'innodb_linux_aio', # existance depends on OS
1920
'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing
2021
order by variable_name;

storage/innobase/handler/ha_innodb.cc

+31
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,25 @@ static TYPELIB innodb_stats_method_typelib = {
313313
NULL
314314
};
315315

316+
/** Possible values for system variable "innodb_linux_aio" */
317+
#ifdef __linux__
318+
static const char* innodb_linux_aio_names[] = {
319+
"auto", /* SRV_LINUX_AIO_AUTO */
320+
"io_uring", /* SRV_LINUX_AIO_IO_URING */
321+
"aio", /* SRV_LINUX_AIO_LIBAIO */
322+
NullS
323+
};
324+
325+
/** Used to define an enumerate type of the system variable
326+
innodb_linux_aio. */
327+
static TYPELIB innodb_linux_aio_typelib = {
328+
array_elements(innodb_linux_aio_names) - 1,
329+
"innodb_linux_aio_typelib",
330+
innodb_linux_aio_names,
331+
NULL
332+
};
333+
#endif
334+
316335
/** Possible values of the parameter innodb_checksum_algorithm */
317336
const char* innodb_checksum_algorithm_names[] = {
318337
"crc32",
@@ -19491,6 +19510,15 @@ static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio,
1949119510
"Use native AIO if supported on this platform.",
1949219511
NULL, NULL, TRUE);
1949319512

19513+
#ifdef __linux__
19514+
static MYSQL_SYSVAR_ENUM(linux_aio, srv_linux_aio_method,
19515+
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
19516+
"Specifies which InnoDB AIO implementaiton should"
19517+
" used. Possible value are \"auto\" (default) to select io_uring"
19518+
" and fallback to aio, or explictly \"io_uring\" and \"aio\"",
19519+
nullptr, nullptr, SRV_LINUX_AIO_AUTO, &innodb_linux_aio_typelib);
19520+
#endif
19521+
1949419522
#ifdef HAVE_LIBNUMA
1949519523
static MYSQL_SYSVAR_BOOL(numa_interleave, srv_numa_interleave,
1949619524
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
@@ -19874,6 +19902,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
1987419902
MYSQL_SYSVAR(autoinc_lock_mode),
1987519903
MYSQL_SYSVAR(version),
1987619904
MYSQL_SYSVAR(use_native_aio),
19905+
#ifdef __linux__
19906+
MYSQL_SYSVAR(linux_aio),
19907+
#endif
1987719908
#ifdef HAVE_LIBNUMA
1987819909
MYSQL_SYSVAR(numa_interleave),
1987919910
#endif /* HAVE_LIBNUMA */

storage/innobase/include/fil0fil.h

+13
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ enum srv_flush_t
7777
#endif
7878
};
7979

80+
/** Possible values of innodb_linux_aio */
81+
#ifdef __linux__
82+
enum srv_linux_aio_t
83+
{
84+
/** auto, io_uring first and then aio */
85+
SRV_LINUX_AIO_AUTO,
86+
/** io_uring */
87+
SRV_LINUX_AIO_IO_URING,
88+
/** aio (libaio interface) */
89+
SRV_LINUX_AIO_LIBAIO
90+
};
91+
#endif
92+
8093
/** innodb_flush_method */
8194
extern ulong srv_file_flush_method;
8295

storage/innobase/include/srv0srv.h

+6
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,12 @@ OS (provided we compiled Innobase with it in), otherwise we will
231231
use simulated aio.
232232
Currently we support native aio on windows and linux */
233233
extern my_bool srv_use_native_aio;
234+
235+
#ifdef __linux__
236+
/* This enum is defined which linux native io method to use */
237+
extern ulong srv_linux_aio_method;
238+
#endif
239+
234240
extern my_bool srv_numa_interleave;
235241

236242
/* Use atomic writes i.e disable doublewrite buffer */

storage/innobase/os/os0file.cc

+39-24
Original file line numberDiff line numberDiff line change
@@ -3387,35 +3387,50 @@ int os_aio_init() noexcept
33873387
int max_read_events= int(srv_n_read_io_threads *
33883388
OS_AIO_N_PENDING_IOS_PER_THREAD);
33893389
int max_events= max_read_events + max_write_events;
3390-
int ret;
3391-
#if LINUX_NATIVE_AIO
3392-
if (srv_use_native_aio && !is_linux_native_aio_supported())
3393-
goto disable;
3394-
#endif
3395-
3396-
ret= srv_thread_pool->configure_aio(srv_use_native_aio, max_events);
3390+
int ret= 1;
33973391

3398-
#ifdef LINUX_NATIVE_AIO
3399-
if (ret)
3392+
#ifdef __linux__
3393+
if (srv_use_native_aio)
34003394
{
3401-
ut_ad(srv_use_native_aio);
3402-
disable:
3403-
ib::warn() << "Linux Native AIO disabled.";
3404-
srv_use_native_aio= false;
3405-
ret= srv_thread_pool->configure_aio(false, max_events);
3406-
}
3395+
switch (srv_linux_aio_method)
3396+
{
3397+
case SRV_LINUX_AIO_AUTO:
3398+
case SRV_LINUX_AIO_IO_URING:
3399+
#ifdef HAVE_URING
3400+
ret= srv_thread_pool->configure_aio(srv_use_native_aio,
3401+
max_events,
3402+
tpool::OS_IO_URING);
34073403
#endif
3408-
3404+
#ifdef LINUX_NATIVE_AIO
34093405
#ifdef HAVE_URING
3410-
if (ret)
3411-
{
3412-
ut_ad(srv_use_native_aio);
3413-
ib::warn()
3414-
<< "liburing disabled: falling back to innodb_use_native_aio=OFF";
3415-
srv_use_native_aio= false;
3416-
ret= srv_thread_pool->configure_aio(false, max_events);
3417-
}
3406+
if (ret && srv_linux_aio_method == SRV_LINUX_AIO_AUTO)
3407+
ib::warn() << "io_uring failed: falling back to libaio";
3408+
else
3409+
break;
3410+
/* fallthough */
3411+
#endif /* HAVE_URING */
3412+
case SRV_LINUX_AIO_LIBAIO:
3413+
ret= srv_thread_pool->configure_aio(srv_use_native_aio,
3414+
max_events,
3415+
tpool::OS_AIO);
3416+
if (!ret && !is_linux_native_aio_supported())
3417+
{
3418+
ret= 1;
3419+
}
34183420
#endif
3421+
}
3422+
if (ret)
3423+
{
3424+
ib::warn() << "native AIO failed: falling back to innodb_use_native_aio=OFF";
3425+
srv_use_native_aio= false;
3426+
}
3427+
}
3428+
#endif /* linux */
3429+
3430+
if (ret)
3431+
ret= srv_thread_pool->configure_aio(srv_use_native_aio,
3432+
max_events,
3433+
tpool::OS_DEFAULT);
34193434

34203435
if (!ret)
34213436
{

storage/innobase/srv/srv0srv.cc

+4
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ OS (provided we compiled Innobase with it in), otherwise we will
138138
use simulated aio we build below with threads.
139139
Currently we support native aio on windows and linux */
140140
my_bool srv_use_native_aio;
141+
#ifdef __linux__
142+
/* This enum is defined which linux native io method to use */
143+
ulong srv_linux_aio_method;
144+
#endif
141145
my_bool srv_numa_interleave;
142146
/** copy of innodb_use_atomic_writes; @see innodb_init_params() */
143147
my_bool srv_use_atomic_writes;

tpool/aio_liburing.cc

+14-6
Original file line numberDiff line numberDiff line change
@@ -206,16 +206,24 @@ namespace tpool
206206
aio *create_libaio(thread_pool* tp, int max_io);
207207
#endif
208208

209-
aio *create_linux_aio(thread_pool *pool, int max_aio)
209+
aio *create_linux_aio(thread_pool *pool, int max_aio, aio_implementation implementation)
210210
{
211-
try {
212-
return new aio_uring(pool, max_aio);
213-
} catch (std::runtime_error& error) {
211+
switch (implementation)
212+
{
213+
case OS_DEFAULT:
214+
case OS_IO_URING:
215+
try {
216+
return new aio_uring(pool, max_aio);
217+
} catch (std::runtime_error& error) {
218+
return nullptr;
219+
}
220+
break;
214221
#ifdef LINUX_NATIVE_AIO
222+
case OS_AIO:
215223
return create_libaio(pool, max_aio);
216-
#else
217-
return nullptr;
218224
#endif
225+
default:
226+
return nullptr;
219227
}
220228
}
221229

tpool/aio_linux.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,10 @@ namespace tpool
180180
{
181181

182182
#ifdef HAVE_URING
183-
# define create_linux_aio create_libaio
183+
aio *create_libaio(thread_pool *pool, int max_io)
184+
#else
185+
aio *create_linux_aio(thread_pool *pool, int max_io, aio_implementation implementation __attribute__((unused)))
184186
#endif
185-
aio *create_linux_aio(thread_pool *pool, int max_io)
186187
{
187188
io_context_t ctx;
188189
memset(&ctx, 0, sizeof ctx);

tpool/tpool.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,21 @@ class thread_pool;
210210

211211
extern aio *create_simulated_aio(thread_pool *tp);
212212

213+
enum aio_implementation
214+
{
215+
OS_DEFAULT
216+
#ifdef __linux__
217+
, OS_IO_URING
218+
, OS_AIO
219+
#endif
220+
};
221+
213222
class thread_pool
214223
{
215224
protected:
216225
/* AIO handler */
217226
std::unique_ptr<aio> m_aio;
218-
virtual aio *create_native_aio(int max_io)= 0;
227+
virtual aio *create_native_aio(int max_io, aio_implementation implementation)= 0;
219228

220229
public:
221230
/**
@@ -238,10 +247,10 @@ class thread_pool
238247
m_worker_init_callback= init;
239248
m_worker_destroy_callback= destroy;
240249
}
241-
int configure_aio(bool use_native_aio, int max_io)
250+
int configure_aio(bool use_native_aio, int max_io, aio_implementation implementation)
242251
{
243252
if (use_native_aio)
244-
m_aio.reset(create_native_aio(max_io));
253+
m_aio.reset(create_native_aio(max_io, implementation));
245254
else
246255
m_aio.reset(create_simulated_aio(this));
247256
return !m_aio ? -1 : 0;

tpool/tpool_generic.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace tpool
4040

4141
#ifdef __linux__
4242
#if defined(HAVE_URING) || defined(LINUX_NATIVE_AIO)
43-
extern aio* create_linux_aio(thread_pool* tp, int max_io);
43+
extern aio* create_linux_aio(thread_pool* tp, int max_io, aio_implementation implementation);
4444
#else
4545
aio *create_linux_aio(thread_pool *, int) { return nullptr; };
4646
#endif
@@ -299,12 +299,12 @@ class thread_pool_generic : public thread_pool
299299
void wait_begin() override;
300300
void wait_end() override;
301301
void submit_task(task *task) override;
302-
aio *create_native_aio(int max_io) override
302+
aio *create_native_aio(int max_io, aio_implementation implementation) override
303303
{
304304
#ifdef _WIN32
305305
return create_win_aio(this, max_io);
306306
#elif defined(__linux__)
307-
return create_linux_aio(this,max_io);
307+
return create_linux_aio(this, max_io, implementation);
308308
#else
309309
return nullptr;
310310
#endif

0 commit comments

Comments
 (0)