From cccd880f435ec5a3b8e417fce5f56116413eb02d Mon Sep 17 00:00:00 2001
From: Chris Packham <chris.packham@alliedtelesis.co.nz>
Date: Mon, 15 Jun 2020 22:01:26 +1200
Subject: [PATCH 2/3] io_uring: Add io_cqring_offset flags

Add support for displaying struct io_cqring_offsets.flags introduced
by Linux kernel commits v5.8-rc1~190^2~22 and v5.8-rc1~190^2~21.

* types/io_uring.h (struct_io_cqring_offsets): Replace resv array
with flags, resv1, and resv2 fields.
* xlat/uring_cqring_flags.in: New file.
* configure.ac (AC_CHECK_MEMBERS): Check struct io_cqring_offsets.flags.
* io_uring.c: Include "xlat/uring_cqring_flags.h".
(SYS_FUNC(io_uring_setup)): Replace printing of the resv array
of struct io_cqring_offsets with flags, resv1, and resv2 fields.
* tests/io_uring_setup.c: Check it.

Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
Resolves: https://github.com/strace/strace/issues/138
---
 configure.ac               |  1 +
 io_uring.c                 | 11 +++++++----
 tests/io_uring_setup.c     | 31 ++++++++++++++++++++++++++-----
 types/io_uring.h           |  4 +++-
 xlat/uring_cqring_flags.in |  1 +
 5 files changed, 38 insertions(+), 10 deletions(-)
 create mode 100644 xlat/uring_cqring_flags.in

diff --git a/configure.ac b/configure.ac
index 7c4f929..958c097 100644
--- a/configure.ac
+++ b/configure.ac
@@ -475,6 +475,7 @@ AC_CHECK_HEADERS([linux/bpf.h], [
 
 AC_CHECK_HEADERS([linux/io_uring.h], [
 	AC_CHECK_MEMBERS(m4_normalize([
+		struct io_cqring_offsets.flags,
 		struct io_uring_params.features,
 		struct io_uring_params.wq_fd,
 		struct io_uring_params.resv
diff --git a/io_uring.c b/io_uring.c
index cfeea82..2ffe163 100644
--- a/io_uring.c
+++ b/io_uring.c
@@ -17,6 +17,7 @@
 #include "xlat/uring_setup_flags.h"
 #include "xlat/uring_enter_flags.h"
 #include "xlat/uring_register_opcodes.h"
+#include "xlat/uring_cqring_flags.h"
 
 #ifdef HAVE_STRUCT_IO_URING_PARAMS
 # ifdef HAVE_STRUCT_IO_URING_PARAMS_RESV
@@ -88,10 +89,12 @@ SYS_FUNC(io_uring_setup)
 		PRINT_FIELD_U(", ", params.cq_off, ring_entries);
 		PRINT_FIELD_U(", ", params.cq_off, overflow);
 		PRINT_FIELD_U(", ", params.cq_off, cqes);
-		if (!IS_ARRAY_ZERO(params.cq_off.resv)) {
-			PRINT_FIELD_ARRAY(", ", params.cq_off, resv, tcp,
-					  print_xint64_array_member);
-		}
+		PRINT_FIELD_FLAGS(", ", params.cq_off, flags,
+				  uring_cqring_flags, "IORING_CQ_???");
+		if (params.cq_off.resv1)
+			PRINT_FIELD_X(", ", params.cq_off, resv1);
+		if (params.cq_off.resv2)
+			PRINT_FIELD_X(", ", params.cq_off, resv2);
 		tprints("}");
 	}
 	tprints("}");
diff --git a/tests/io_uring_setup.c b/tests/io_uring_setup.c
index 317b0d7..a59e4a1 100644
--- a/tests/io_uring_setup.c
+++ b/tests/io_uring_setup.c
@@ -27,6 +27,7 @@
 # include "xlat.h"
 
 # include "xlat/uring_setup_features.h"
+# include "xlat/uring_cqring_flags.h"
 
 # ifdef HAVE_STRUCT_IO_URING_PARAMS_FEATURES
 #  ifdef HAVE_STRUCT_IO_URING_PARAMS_WQ_FD
@@ -144,20 +145,40 @@ main(void)
 						params->sq_off.resv2);
 
 			printf("}, cq_off={head=%u, tail=%u, ring_mask=%u"
-			       ", ring_entries=%u, overflow=%u, cqes=%u",
+			       ", ring_entries=%u, overflow=%u, cqes=%u, flags=",
 			       params->cq_off.head,
 			       params->cq_off.tail,
 			       params->cq_off.ring_mask,
 			       params->cq_off.ring_entries,
 			       params->cq_off.overflow,
 			       params->cq_off.cqes);
-			if (params->cq_off.resv[0] || params->cq_off.resv[1]) {
-				printf(", resv=[%#llx, %#llx]",
+#ifdef HAVE_STRUCT_IO_CQRING_OFFSETS_FLAGS
+			printflags(uring_cqring_flags,
+			       params->cq_off.flags,
+			       "IORING_CQ_???");
+			if (params->cq_off.resv1)
+				printf(", resv1=%#x", params->cq_off.resv1);
+			if (params->cq_off.resv2)
+				printf(", resv2=%#llx",
 				       (unsigned long long)
-						params->cq_off.resv[0],
+						params->cq_off.resv2);
+#else
+			union {
+				struct {
+					uint32_t flags;
+					uint32_t resv1;
+				} s;
+				uint64_t v;
+			} u = { .v = params->cq_off.resv[0] };
+			printflags(uring_cqring_flags, u.s.flags,
+				   "IORING_CQ_???");
+			if (u.s.resv1)
+				printf(", resv1=%#x", u.s.resv1);
+			if (params->cq_off.resv[1])
+				printf(", resv2=%#llx",
 				       (unsigned long long)
 						params->cq_off.resv[1]);
-			}
+#endif
 
 			printf("}}) = %ld<anon_inode:[io_uring]>\n", rc);
 		}
diff --git a/types/io_uring.h b/types/io_uring.h
index 76f432c..2fe1c13 100644
--- a/types/io_uring.h
+++ b/types/io_uring.h
@@ -31,7 +31,9 @@ typedef struct {
 	uint32_t ring_entries;
 	uint32_t overflow;
 	uint32_t cqes;
-	uint64_t resv[2];
+	/** Added by v5.8-rc1~190^2~22 */	uint32_t flags;
+	/** Added by v5.8-rc1~190^2~22 */	uint32_t resv1;
+	/** Added by v5.8-rc1~190^2~22 */	uint64_t resv2;
 } struct_io_cqring_offsets;
 
 typedef struct {
diff --git a/xlat/uring_cqring_flags.in b/xlat/uring_cqring_flags.in
new file mode 100644
index 0000000..c81fbc2
--- /dev/null
+++ b/xlat/uring_cqring_flags.in
@@ -0,0 +1 @@
+IORING_CQ_EVENTFD_DISABLED	1U
-- 
2.27.0

