[PATCH] check kernel version for io_method

Started by Pierre Forstmann10 days ago11 messages
#1Pierre Forstmann
pierre.forstmann@gmail.com
1 attachment(s)

Hello,

Please find a patch proposal for bug BUG #19369: Not documented that
io_uring on kernel versions between 5.1 and below 5.6 does not work.

This is not  a document patch but code patch using a GUC hook to :

- check liburing setup

- check kernel version

to allow/disallow io_method=io_uring

I have made successfull tests on:

- Alma Linux 9.7/ kernel 5.14 without liburing setup

- Debian 12 / kernel 6.1 with liburing-dev

NB:

This is my first patch and I apologize if it is not fully compliant with
patching rules.

Thanks.

Attachments:

0001-patch-check-kernel-version-for-io_method.patchtext/x-patch; charset=UTF-8; name=0001-patch-check-kernel-version-for-io_method.patchDownload
From 8e0bd6948f7a75472891965b126356903934dfd2 Mon Sep 17 00:00:00 2001
From: Pierre Forstmann <pierre.forstmann@gmail.com>
Date: Tue, 13 Jan 2026 22:53:03 +0100
Subject: [PATCH] patch: check kernel version for io_method

---
 src/backend/storage/aio/aio.c             | 47 +++++++++++++++++++++++
 src/backend/utils/misc/guc_parameters.dat |  1 +
 src/include/utils/guc_hooks.h             |  2 +
 3 files changed, 50 insertions(+)

diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c
index d2c9cd6f20a..f7610498467 100644
--- a/src/backend/storage/aio/aio.c
+++ b/src/backend/storage/aio/aio.c
@@ -50,6 +50,7 @@
 #include "utils/resowner.h"
 #include "utils/wait_event_types.h"
 
+#include <sys/utsname.h>
 
 static inline void pgaio_io_update_state(PgAioHandle *ioh, PgAioHandleState new_state);
 static void pgaio_io_reclaim(PgAioHandle *ioh);
@@ -1346,3 +1347,49 @@ check_io_max_concurrency(int *newval, void **extra, GucSource source)
 
 	return true;
 }
+
+
+bool
+check_io_method(int *newval, void **extra, GucSource source) 
+{
+#ifdef IOMETHOD_IO_URING_ENABLED
+	if (*newval == IOMETHOD_IO_URING)
+	{
+		struct utsname uname_buf;
+		int major;
+		int minor;
+		int rc;
+
+		uname(&uname_buf);
+	 	rc = sscanf(uname_buf.release, "%d.%d", &major, &minor);
+
+		if (rc == 2 && ((major >= 5 && minor >= 6) || major >= 6))             
+		{
+			/*
+			 * OK
+			 */
+		}
+		else 
+        	{
+			GUC_check_errdetail("io_uring requires Linux kernel 5.6 or later.");
+			return false;
+        	}
+	}	
+
+	return true;
+#else
+	if (*newval == IOMETHOD_WORKER || *newval == IOMETHOD_SYNC)
+	{
+		/*
+		 * OK
+		 */
+	} 
+	else 
+	{
+		GUC_check_errdetail("io_uring requires Linux kernel 5.6 or later.");
+		return false;
+	}
+
+	return true;
+#endif
+}
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index 7c60b125564..2246af79808 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -1339,6 +1339,7 @@
   boot_val => 'DEFAULT_IO_METHOD',
   options => 'io_method_options',
   assign_hook => 'assign_io_method',
+  check_hook => 'check_io_method',
 },
 
 { name => 'io_workers', type => 'int', context => 'PGC_SIGHUP', group => 'RESOURCES_IO',
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index f723668da9e..1c33dff4b55 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -176,4 +176,6 @@ extern bool check_synchronized_standby_slots(char **newval, void **extra,
 											 GucSource source);
 extern void assign_synchronized_standby_slots(const char *newval, void *extra);
 
+extern bool check_io_method(int *newval, void **extra, GucSource source);
+
 #endif							/* GUC_HOOKS_H */
-- 
2.47.3

#2Andreas Karlsson
andreas.karlsson@percona.com
In reply to: Pierre Forstmann (#1)
Re: [PATCH] check kernel version for io_method

On 1/13/26 11:05 PM, Pierre wrote:

Please find a patch proposal for bug BUG #19369: Not documented that
io_uring on kernel versions between 5.1 and below 5.6 does not work.

Wouldn't it make more sense to use io_uring_get_probe_ring() and
io_uring_opcode_supported() to actually check for the required opcode?
Then if someone uses a Kernel with the required features backported
everything will still work.

Andreas

#3Steven Niu
niushiji@gmail.com
In reply to: Andreas Karlsson (#2)
Re: [PATCH] check kernel version for io_method

From: Andreas Karlsson <andreas@proxel.se>
Sent: Wednesday, January 14, 2026 09:07
To: Pierre <pierre.forstmann@gmail.com>; pgsql-hackers@lists.postgresql.org <pgsql-hackers@lists.postgresql.org>
Subject: Re: [PATCH] check kernel version for io_method

On 1/13/26 11:05 PM, Pierre wrote:

Please find a patch proposal for bug BUG #19369: Not documented that
io_uring on kernel versions between 5.1 and below 5.6 does not work.

Wouldn't it make more sense to use io_uring_get_probe_ring() and
io_uring_opcode_supported() to actually check for the required opcode?
Then if someone uses a Kernel with the required features backported
everything will still work.

Andreas

+1
It would be more reliable to check the availability of io_uring feature than to check OS version.

BTW, the error message in the following code block is wrong as it locates in branch that IO_URING is not enabled.

#else
+	if (*newval == IOMETHOD_WORKER || *newval == IOMETHOD_SYNC)
+	{
+		/*
+		 * OK
+		 */
+	} 
+	else 
+	{
+		GUC_check_errdetail("io_uring requires Linux kernel 5.6 or later.");
+		return false;
+	}

Thanks,
Steven

#4Andreas Karlsson
andreas.karlsson@percona.com
In reply to: Steven Niu (#3)
Re: [PATCH] check kernel version for io_method

On 1/14/26 3:31 AM, Steven Niu wrote:

BTW, the error message in the following code block is wrong as it locates in branch that IO_URING is not enabled.

#else
+	if (*newval == IOMETHOD_WORKER || *newval == IOMETHOD_SYNC)
+	{
+		/*
+		 * OK
+		 */
+	}
+	else
+	{
+		GUC_check_errdetail("io_uring requires Linux kernel 5.6 or later.");
+		return false;
+	}

That code is unreachable so it should just be deleted. Look at the enum.

/* Enum for io_method GUC. */
typedef enum IoMethod
{
IOMETHOD_SYNC = 0,
IOMETHOD_WORKER,
#ifdef IOMETHOD_IO_URING_ENABLED
IOMETHOD_IO_URING,
#endif
} IoMethod;

Andreas

#5Steven Niu
niushiji@gmail.com
In reply to: Andreas Karlsson (#4)
Re: [PATCH] check kernel version for io_method

From: Andreas Karlsson <andreas@proxel.se>
Sent: Wednesday, January 14, 2026 11:09
To: Steven Niu <niushiji@gmail.com>; Pierre <pierre.forstmann@gmail.com>; pgsql-hackers@lists.postgresql.org <pgsql-hackers@lists.postgresql.org>
Subject: Re: [PATCH] check kernel version for io_method

On 1/14/26 3:31 AM, Steven Niu wrote:

BTW, the error message in the following code block is wrong as it locates in branch that IO_URING is not enabled.

#else
+     if (*newval == IOMETHOD_WORKER || *newval == IOMETHOD_SYNC)
+     {
+             /*
+              * OK
+              */
+     }
+     else
+     {
+             GUC_check_errdetail("io_uring requires Linux kernel 5.6 or later.");
+             return false;
+     }

That code is unreachable so it should just be deleted. Look at the enum.

/* Enum for io_method GUC. */
typedef enum IoMethod
{
        IOMETHOD_SYNC = 0,
        IOMETHOD_WORKER,
#ifdef IOMETHOD_IO_URING_ENABLED
        IOMETHOD_IO_URING,
#endif
}                       IoMethod;

Andreas

________________________________________

Hi, Andreas,

I agree that you are correct for now. But in future, the IoMethod may have new member. Then we have to process it.

How about change to like this:
 + #else
 +     if (*newval == IOMETHOD_IO_URING)
 +     {
 +             GUC_check_errdetail("io_uring not enabled.");
 +             return false;
 +     }

Thanks,
Steven

#6Andreas Karlsson
andreas.karlsson@percona.com
In reply to: Steven Niu (#5)
Re: [PATCH] check kernel version for io_method

On 1/14/26 8:22 AM, Steven Niu wrote:

I agree that you are correct for now. But in future, the IoMethod may have new member. Then we have to process it.

How about change to like this:
+ #else
+     if (*newval == IOMETHOD_IO_URING)
+     {
+             GUC_check_errdetail("io_uring not enabled.");
+             return false;
+     }

No, that would be incorrect. It would not even compile.
IOMETHOD_IO_URING is not even defined if we do not compile with liburing
enabled. You can try it out yourself by compiling PostgreSQL without
io_uring support and then try to enable it. You will get an error and
that code will never be reached.

Andreas

#7Steven Niu
niushiji@gmail.com
In reply to: Andreas Karlsson (#6)
Re: [PATCH] check kernel version for io_method

From: Andreas Karlsson <andreas@proxel.se>
Sent: Wednesday, January 14, 2026 15:27
To: Steven Niu <niushiji@gmail.com>; Pierre <pierre.forstmann@gmail.com>; pgsql-hackers@lists.postgresql.org <pgsql-hackers@lists.postgresql.org>
Subject: Re: [PATCH] check kernel version for io_method

On 1/14/26 8:22 AM, Steven Niu wrote:

I agree that you are correct for now. But in future, the IoMethod may have new member. Then we have to process it.

How about change to like this:
   + #else
   +     if (*newval == IOMETHOD_IO_URING)
   +     {
   +             GUC_check_errdetail("io_uring not enabled.");
   +             return false;
   +     }

No, that would be incorrect. It would not even compile.
IOMETHOD_IO_URING is not even defined if we do not compile with liburing
enabled. You can try it out yourself by compiling PostgreSQL without
io_uring support and then try to enable it. You will get an error and
that code will never be reached.

Andreas

________________________________________

Yes, you are definitely correct.
I'd like to withdwar my proposal.

#8Pierre Forstmann
pierre.forstmann@gmail.com
In reply to: Steven Niu (#7)
1 attachment(s)
Re: [PATCH] check kernel version for io_method

Le 14/01/2026 à 08:31, Steven Niu a écrit :

From: Andreas Karlsson <andreas@proxel.se>
Sent: Wednesday, January 14, 2026 15:27
To: Steven Niu <niushiji@gmail.com>; Pierre <pierre.forstmann@gmail.com>; pgsql-hackers@lists.postgresql.org <pgsql-hackers@lists.postgresql.org>
Subject: Re: [PATCH] check kernel version for io_method

On 1/14/26 8:22 AM, Steven Niu wrote:

I agree that you are correct for now. But in future, the IoMethod may have new member. Then we have to process it.

How about change to like this:
   + #else
   +     if (*newval == IOMETHOD_IO_URING)
   +     {
   +             GUC_check_errdetail("io_uring not enabled.");
   +             return false;
   +     }

No, that would be incorrect. It would not even compile.
IOMETHOD_IO_URING is not even defined if we do not compile with liburing
enabled. You can try it out yourself by compiling PostgreSQL without
io_uring support and then try to enable it. You will get an error and
that code will never be reached.

Andreas

________________________________________

Yes, you are definitely correct.
I'd like to withdwar my proposal.

Hello,

I have modified message in case io_uring is not enabled when building
PG. But currently I cannot test it, GUC parameter is rejected in earlier
steps:

pg_ctl start
waiting for server to start....2026-01-14 09:35:37.046 GMT [16336] LOG: 
invalid value for parameter "io_method": "io_uring"
2026-01-14 09:35:37.046 GMT [16336] HINT:  Available values: sync, worker.
2026-01-14 10:35:37.047 CET [16336] FATAL:  configuration file
"/home/pierre/pgdata/postgresql.conf" contains errors
 stopped waiting
pg_ctl: could not start server

I don't know how to test io_uring features in code because if io_uring
is not enabled at compilation time, I don't think it is possible to
compile code calling  io_uring_get_probe_ring() or
io_uring_opcode_supported() ?

Thanks.

Attachments:

0002-patch-check-kernel-version-for-io_method.patchtext/x-patch; charset=UTF-8; name=0002-patch-check-kernel-version-for-io_method.patchDownload
diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c
index d2c9cd6f20a..707f79352c7 100644
--- a/src/backend/storage/aio/aio.c
+++ b/src/backend/storage/aio/aio.c
@@ -50,6 +50,7 @@
 #include "utils/resowner.h"
 #include "utils/wait_event_types.h"
 
+#include <sys/utsname.h>
 
 static inline void pgaio_io_update_state(PgAioHandle *ioh, PgAioHandleState new_state);
 static void pgaio_io_reclaim(PgAioHandle *ioh);
@@ -1346,3 +1347,49 @@ check_io_max_concurrency(int *newval, void **extra, GucSource source)
 
 	return true;
 }
+
+
+bool
+check_io_method(int *newval, void **extra, GucSource source) 
+{
+#ifdef IOMETHOD_IO_URING_ENABLED
+	if (*newval == IOMETHOD_IO_URING)
+	{
+		struct utsname uname_buf;
+		int major;
+		int minor;
+		int rc;
+
+		uname(&uname_buf);
+	 	rc = sscanf(uname_buf.release, "%d.%d", &major, &minor);
+
+		if (rc == 2 && ((major >= 5 && minor >= 6) || major >= 6))             
+		{
+			/*
+			 * OK
+			 */
+		}
+		else 
+        	{
+			GUC_check_errdetail("io_uring requires Linux kernel 5.6 or later.");
+			return false;
+        	}
+	}	
+
+	return true;
+#else
+	if (*newval == IOMETHOD_WORKER || *newval == IOMETHOD_SYNC)
+	{
+		/*
+		 * OK
+		 */
+	} 
+	else 
+	{
+		GUC_check_errdetail("io_uring is not enabled.");
+		return false;
+	}
+
+	return true;
+#endif
+}
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index 7c60b125564..2246af79808 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -1339,6 +1339,7 @@
   boot_val => 'DEFAULT_IO_METHOD',
   options => 'io_method_options',
   assign_hook => 'assign_io_method',
+  check_hook => 'check_io_method',
 },
 
 { name => 'io_workers', type => 'int', context => 'PGC_SIGHUP', group => 'RESOURCES_IO',
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index f723668da9e..1c33dff4b55 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -176,4 +176,6 @@ extern bool check_synchronized_standby_slots(char **newval, void **extra,
 											 GucSource source);
 extern void assign_synchronized_standby_slots(const char *newval, void *extra);
 
+extern bool check_io_method(int *newval, void **extra, GucSource source);
+
 #endif							/* GUC_HOOKS_H */
#9Jakub Wartak
jakub.wartak@enterprisedb.com
In reply to: Steven Niu (#3)
Re: [PATCH] check kernel version for io_method

On Wed, Jan 14, 2026 at 3:31 AM Steven Niu <niushiji@gmail.com> wrote:

From: Andreas Karlsson <andreas@proxel.se>
Sent: Wednesday, January 14, 2026 09:07
To: Pierre <pierre.forstmann@gmail.com>; pgsql-hackers@lists.postgresql.org <pgsql-hackers@lists.postgresql.org>
Subject: Re: [PATCH] check kernel version for io_method

On 1/13/26 11:05 PM, Pierre wrote:

Please find a patch proposal for bug BUG #19369: Not documented that
io_uring on kernel versions between 5.1 and below 5.6 does not work.

Wouldn't it make more sense to use io_uring_get_probe_ring() and
io_uring_opcode_supported() to actually check for the required opcode?
Then if someone uses a Kernel with the required features backported
everything will still work.

Andreas

+1
It would be more reliable to check the availability of io_uring feature than to check OS version.

Hi,

I haven't looked at this patch, however the above statement is not
completely true. There is a parallel problem [1]/messages/by-id/CAKZiRmzxj6Lt1w2ffDoUmN533TgyDeYVULEH1PQFLRyBJSFP6w@mail.gmail.com related to kernel
version, where if you do not run proper kernel version (>= 6.5) or
proper liburing version, then fork() (-> all connections established)
are going to be slow slugging under more than basic load due to lack
of "combined memory mapping creation" (so technically speaking
recommending someone to go to 5.6.x but < 6.5 IMHO is also not good
advice). See first message in that [1]/messages/by-id/CAKZiRmzxj6Lt1w2ffDoUmN533TgyDeYVULEH1PQFLRyBJSFP6w@mail.gmail.com for a performance report about
this. IMHVO if we are checking for kernel versions we could also warn
about performance regression (something like merge those two patches
if one wants to have a good io_uring experience).

-J.

[1]: /messages/by-id/CAKZiRmzxj6Lt1w2ffDoUmN533TgyDeYVULEH1PQFLRyBJSFP6w@mail.gmail.com

#10Pierre Forstmann
pierre.forstmann@gmail.com
In reply to: Pierre Forstmann (#8)
1 attachment(s)
Re: [PATCH] check kernel version for io_method

OK I was wrong: I can use io_uring_get_probe() if postgres has been
built with liburing flag.

So I have replaced uname() call by io_uring_get_probe() call and I have
modified the error messages: Linux kernel version is neither directly
used  nor mentioned.

Le 14/01/2026 à 11:18, Pierre a écrit :

Show quoted text

Le 14/01/2026 à 08:31, Steven Niu a écrit :

From: Andreas Karlsson <andreas@proxel.se>
Sent: Wednesday, January 14, 2026 15:27
To: Steven Niu <niushiji@gmail.com>; Pierre
<pierre.forstmann@gmail.com>; pgsql-hackers@lists.postgresql.org
<pgsql-hackers@lists.postgresql.org>
Subject: Re: [PATCH] check kernel version for io_method

On 1/14/26 8:22 AM, Steven Niu wrote:

I agree that you are correct for now. But in future, the IoMethod
may have new member. Then we have to process it.

How about change to like this:
    + #else
    +     if (*newval == IOMETHOD_IO_URING)
    +     {
    +             GUC_check_errdetail("io_uring not enabled.");
    +             return false;
    +     }

No, that would be incorrect. It would not even compile.
IOMETHOD_IO_URING is not even defined if we do not compile with liburing
enabled. You can try it out yourself by compiling PostgreSQL without
io_uring support and then try to enable it. You will get an error and
that code will never be reached.

Andreas

________________________________________

Yes, you are definitely correct.
I'd like to withdwar my proposal.

Hello,

I have modified message in case io_uring is not enabled when building
PG. But currently I cannot test it, GUC parameter is rejected in
earlier steps:

pg_ctl start
waiting for server to start....2026-01-14 09:35:37.046 GMT [16336]
LOG:  invalid value for parameter "io_method": "io_uring"
2026-01-14 09:35:37.046 GMT [16336] HINT:  Available values: sync,
worker.
2026-01-14 10:35:37.047 CET [16336] FATAL:  configuration file
"/home/pierre/pgdata/postgresql.conf" contains errors
 stopped waiting
pg_ctl: could not start server

I don't know how to test io_uring features in code because if io_uring
is not enabled at compilation time, I don't think it is possible to
compile code calling  io_uring_get_probe_ring() or
io_uring_opcode_supported() ?

Thanks.

Attachments:

0003-patch-check-kernel-support-for-io-uring.patchtext/x-patch; charset=UTF-8; name=0003-patch-check-kernel-support-for-io-uring.patchDownload
diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c
index d2c9cd6f20a..6fb5d3d5dee 100644
--- a/src/backend/storage/aio/aio.c
+++ b/src/backend/storage/aio/aio.c
@@ -50,6 +50,9 @@
 #include "utils/resowner.h"
 #include "utils/wait_event_types.h"
 
+#ifdef IOMETHOD_IO_URING_ENABLED
+#include <liburing.h>
+#endif
 
 static inline void pgaio_io_update_state(PgAioHandle *ioh, PgAioHandleState new_state);
 static void pgaio_io_reclaim(PgAioHandle *ioh);
@@ -1346,3 +1349,37 @@ check_io_max_concurrency(int *newval, void **extra, GucSource source)
 
 	return true;
 }
+
+
+bool
+check_io_method(int *newval, void **extra, GucSource source) 
+{
+#ifdef IOMETHOD_IO_URING_ENABLED
+	if (*newval == IOMETHOD_IO_URING)
+	{
+		struct io_uring_probe *probe = io_uring_get_probe();
+
+		if (probe == NULL)             
+		{
+			GUC_check_errdetail("liburing probe is not supported by this operating system kernel: setting io_method to io_uring is not possible.");
+			return false;
+		}
+	}	
+
+	return true;
+#else
+	if (*newval == IOMETHOD_WORKER || *newval == IOMETHOD_SYNC)
+	{
+		/*
+		 * OK
+		 */
+	} 
+	else 
+	{
+		GUC_check_errdetail("liburing has not been enabled at build time for this executable: setting io_method to io_uring is not possible.");
+		return false;
+	}
+
+	return true;
+#endif
+}
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index 7c60b125564..2246af79808 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -1339,6 +1339,7 @@
   boot_val => 'DEFAULT_IO_METHOD',
   options => 'io_method_options',
   assign_hook => 'assign_io_method',
+  check_hook => 'check_io_method',
 },
 
 { name => 'io_workers', type => 'int', context => 'PGC_SIGHUP', group => 'RESOURCES_IO',
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index f723668da9e..1c33dff4b55 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -176,4 +176,6 @@ extern bool check_synchronized_standby_slots(char **newval, void **extra,
 											 GucSource source);
 extern void assign_synchronized_standby_slots(const char *newval, void *extra);
 
+extern bool check_io_method(int *newval, void **extra, GucSource source);
+
 #endif							/* GUC_HOOKS_H */
#11Andreas Karlsson
andreas.karlsson@percona.com
In reply to: Jakub Wartak (#9)
Re: [PATCH] check kernel version for io_method

On 1/14/26 12:14 PM, Jakub Wartak wrote:

I haven't looked at this patch, however the above statement is not
completely true. There is a parallel problem [1] related to kernel
version, where if you do not run proper kernel version (>= 6.5) or
proper liburing version, then fork() (-> all connections established)
are going to be slow slugging under more than basic load due to lack
of "combined memory mapping creation" (so technically speaking
recommending someone to go to 5.6.x but < 6.5 IMHO is also not good
advice). See first message in that [1] for a performance report about
this. IMHVO if we are checking for kernel versions we could also warn
about performance regression (something like merge those two patches
if one wants to have a good io_uring experience).

We can probe for that too, which we already do. If you call
pgaio_uring_ring_shmem_size() it will return 0 on Linux <6.5. Which I
think eve further supports probing for the features we need rather than
looking at the kernel version.

Andreas