mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4 0/3] io_uring: add fremovexattr and flistxattr support
@ 2026-09-18  9:00 Aditya Prakash Srivastava
  2026-09-18  9:00 ` [PATCH v4 1/3] tools: sync io_uring.h UAPI header Aditya Prakash Srivastava
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Aditya Prakash Srivastava @ 2026-09-18  9:00 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner, Gabriel Krisman Bertazi
  Cc: Alexander Viro, Jan Kara, io-uring, linux-fsdevel, linux-kernel,
	Aditya Prakash Srivastava

This series completes io_uring's FD-based xattr operations by adding
support for:
- IORING_OP_FREMOVEXATTR
- IORING_OP_FLISTXATTR

This allows asynchronous xattr removal and listing.

New test cases have been added to the liburing test suite
(test/xattr.c) and verified to pass. A separate userspace patch
implementing the matching prep helpers, sanitizers, and test cases
has been updated and submitted in parallel.

- Patch 1 syncs the tools/ directory's io_uring.h UAPI header to
  align it with kernel mainline prior to introducing the new opcodes.
- Patch 2 makes the necessary VFS-layer list/remove helpers
  non-static and declares them in fs/internal.h.
- Patch 3 implements the io_uring operational support (opcodes,
  opdefs, preparation, and issue handlers) and invokes these helpers.

Changes since v3:
- Split the tools/ UAPI header sync of pre-existing mainline opcodes
  into a separate precursor patch (Patch 1) (Suggested by Gabriel).
- Robustify io_fremovexattr_prep by initializing kname and kvalue
  to NULL to avoid potential garbage-pointer crashes in the
  io_xattr_cleanup path (Reported by Gabriel).
- Add strict validation to both fremovexattr and flistxattr to
  zero-check and reject all unused SQE fields (Reported by Gabriel).
- Reset ix->ctx.kname to NULL on error inside io_fremovexattr_prep.

Changes since v2:
- Revert unnecessary formatting changes to filename_listxattr in
  Patch 1 (now Patch 2).

Changes since v1:
- Omit path-based opcodes to prioritize optimal FD-based variants.
- Limit exported VFS helpers to only file_listxattr and
  file_removexattr.
- Rewrite standalone test program into a standard liburing testcase.

Aditya Prakash Srivastava (3):
  tools: sync io_uring.h UAPI header
  fs: make file_listxattr and file_removexattr helpers non-static
  io_uring: add fremovexattr and flistxattr support

 fs/internal.h                       |   2 +
 fs/xattr.c                          |   3 +-
 include/uapi/linux/io_uring.h       |   2 +
 io_uring/opdef.c                    |  18 ++
 io_uring/xattr.c                    |  83 +++++++
 io_uring/xattr.h                    |   6 +
 tools/include/uapi/linux/io_uring.h | 342 ++++++++++++++++++++++++++--
 7 files changed, 438 insertions(+), 18 deletions(-)

-- 
2.47.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 1/3] tools: sync io_uring.h UAPI header
  2026-09-18  9:00 [PATCH v4 0/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava
@ 2026-09-18  9:00 ` Aditya Prakash Srivastava
  2026-09-18 16:49   ` Caleb Sander Mateos
  2026-09-18  9:00 ` [PATCH v4 2/3] fs: make file_listxattr and file_removexattr helpers non-static Aditya Prakash Srivastava
  2026-09-18  9:00 ` [PATCH v4 3/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava
  2 siblings, 1 reply; 5+ messages in thread
From: Aditya Prakash Srivastava @ 2026-09-18  9:00 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner, Gabriel Krisman Bertazi
  Cc: Alexander Viro, Jan Kara, io-uring, linux-fsdevel, linux-kernel,
	Aditya Prakash Srivastava

Sync tools/include/uapi/linux/io_uring.h with the main kernel
include/uapi/linux/io_uring.h UAPI header to ensure they are
perfectly aligned.

Additionally, correct a minor space-before-tab checkpatch.pl warning
in the comments of both headers (no functional change).

Suggested-by: Gabriel Krisman Bertazi <krisman@suse.de>
Signed-off-by: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
---
 include/uapi/linux/io_uring.h       |   2 +-
 tools/include/uapi/linux/io_uring.h | 340 ++++++++++++++++++++++++++--
 2 files changed, 325 insertions(+), 17 deletions(-)

diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 909fb7aea638..1f300f6b85d7 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -426,7 +426,7 @@ enum io_uring_op {
  * IORING_RECVSEND_BUNDLE	Used with IOSQE_BUFFER_SELECT. If set, send or
  *				recv will grab as many buffers from the buffer
  *				group ID given and send them all. The completion
- *				result 	will be the number of buffers send, with
+ *				result	will be the number of buffers send, with
  *				the starting buffer ID in cqe->flags as per
  *				usual for provided buffer usage. The buffers
  *				will be	contiguous from the starting buffer ID.
diff --git a/tools/include/uapi/linux/io_uring.h b/tools/include/uapi/linux/io_uring.h
index f1c16f817742..1f300f6b85d7 100644
--- a/tools/include/uapi/linux/io_uring.h
+++ b/tools/include/uapi/linux/io_uring.h
@@ -10,6 +10,8 @@
 
 #include <linux/fs.h>
 #include <linux/types.h>
+#include <linux/io_uring/zcrx.h>
+
 /*
  * this file is shared with liburing and that has to autodetect
  * if linux/time_types.h is available or not, it can
@@ -50,7 +52,7 @@ struct io_uring_sqe {
 	};
 	__u32	len;		/* buffer size or number of iovecs */
 	union {
-		__kernel_rwf_t	rw_flags;
+		__u32		rw_flags;
 		__u32		fsync_flags;
 		__u16		poll_events;	/* compatibility */
 		__u32		poll32_events;	/* word-reversed for BE */
@@ -71,6 +73,9 @@ struct io_uring_sqe {
 		__u32		uring_cmd_flags;
 		__u32		waitid_flags;
 		__u32		futex_flags;
+		__u32		install_fd_flags;
+		__u32		nop_flags;
+		__u32		pipe_flags;
 	};
 	__u64	user_data;	/* data to be passed back at completion time */
 	/* pack this to avoid bogus arm OABI complaints */
@@ -85,17 +90,26 @@ struct io_uring_sqe {
 	union {
 		__s32	splice_fd_in;
 		__u32	file_index;
+		__u32	zcrx_ifq_idx;
 		__u32	optlen;
 		struct {
 			__u16	addr_len;
 			__u16	__pad3[1];
 		};
+		struct {
+			__u8	write_stream;
+			__u8	__pad4[3];
+		};
 	};
 	union {
 		struct {
 			__u64	addr3;
 			__u64	__pad2[1];
 		};
+		struct {
+			__u64	attr_ptr; /* pointer to attribute information */
+			__u64	attr_type_mask; /* bit mask of attributes */
+		};
 		__u64	optval;
 		/*
 		 * If the ring is initialized with IORING_SETUP_SQE128, then
@@ -105,6 +119,18 @@ struct io_uring_sqe {
 	};
 };
 
+/* sqe->attr_type_mask flags */
+#define IORING_RW_ATTR_FLAG_PI	(1U << 0)
+/* PI attribute information */
+struct io_uring_attr_pi {
+		__u16	flags;
+		__u16	app_tag;
+		__u32	len;
+		__u64	addr;
+		__u64	seed;
+		__u64	rsvd;
+};
+
 /*
  * If sqe->file_index is set to this for opcodes that instantiate a new
  * direct descriptor (like openat/openat2/accept), then io_uring will allocate
@@ -114,7 +140,7 @@ struct io_uring_sqe {
  */
 #define IORING_FILE_INDEX_ALLOC		(~0U)
 
-enum {
+enum io_uring_sqe_flags_bit {
 	IOSQE_FIXED_FILE_BIT,
 	IOSQE_IO_DRAIN_BIT,
 	IOSQE_IO_LINK_BIT,
@@ -164,7 +190,8 @@ enum {
 /*
  * If COOP_TASKRUN is set, get notified if task work is available for
  * running and a kernel transition would be needed to run it. This sets
- * IORING_SQ_TASKRUN in the sq ring flags. Not valid with COOP_TASKRUN.
+ * IORING_SQ_TASKRUN in the sq ring flags. Not valid without COOP_TASKRUN
+ * or DEFER_TASKRUN.
  */
 #define IORING_SETUP_TASKRUN_FLAG	(1U << 9)
 #define IORING_SETUP_SQE128		(1U << 10) /* SQEs are 128 byte */
@@ -198,6 +225,33 @@ enum {
  */
 #define IORING_SETUP_NO_SQARRAY		(1U << 16)
 
+/* Use hybrid poll in iopoll process */
+#define IORING_SETUP_HYBRID_IOPOLL	(1U << 17)
+
+/*
+ * Allow both 16b and 32b CQEs. If a 32b CQE is posted, it will have
+ * IORING_CQE_F_32 set in cqe->flags.
+ */
+#define IORING_SETUP_CQE_MIXED		(1U << 18)
+
+/*
+ * Allow both 64b and 128b SQEs. If a 128b SQE is posted, it will have
+ * a 128b opcode.
+ */
+#define IORING_SETUP_SQE_MIXED		(1U << 19)
+
+/*
+ * When set, io_uring ignores SQ head and tail and fetches SQEs to submit
+ * starting from index 0 instead from the index stored in the head pointer.
+ * IOW, the user should place all SQE at the beginning of the SQ memory
+ * before issuing a submission syscall.
+ *
+ * It requires IORING_SETUP_NO_SQARRAY and is incompatible with
+ * IORING_SETUP_SQPOLL. The user must also never change the SQ head and tail
+ * values and keep it set to 0. Any other value is undefined behaviour.
+ */
+#define IORING_SETUP_SQ_REWIND		(1U << 20)
+
 enum io_uring_op {
 	IORING_OP_NOP,
 	IORING_OP_READV,
@@ -253,6 +307,17 @@ enum io_uring_op {
 	IORING_OP_FUTEX_WAIT,
 	IORING_OP_FUTEX_WAKE,
 	IORING_OP_FUTEX_WAITV,
+	IORING_OP_FIXED_FD_INSTALL,
+	IORING_OP_FTRUNCATE,
+	IORING_OP_BIND,
+	IORING_OP_LISTEN,
+	IORING_OP_RECV_ZC,
+	IORING_OP_EPOLL_WAIT,
+	IORING_OP_READV_FIXED,
+	IORING_OP_WRITEV_FIXED,
+	IORING_OP_PIPE,
+	IORING_OP_NOP128,
+	IORING_OP_URING_CMD128,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
@@ -262,9 +327,13 @@ enum io_uring_op {
  * sqe->uring_cmd_flags		top 8bits aren't available for userspace
  * IORING_URING_CMD_FIXED	use registered buffer; pass this flag
  *				along with setting sqe->buf_index.
+ * IORING_URING_CMD_MULTISHOT	must be used with buffer select, like other
+ *				multishot commands. Not compatible with
+ *				IORING_URING_CMD_FIXED, for now.
  */
 #define IORING_URING_CMD_FIXED	(1U << 0)
-#define IORING_URING_CMD_MASK	IORING_URING_CMD_FIXED
+#define IORING_URING_CMD_MULTISHOT	(1U << 1)
+#define IORING_URING_CMD_MASK	(IORING_URING_CMD_FIXED | IORING_URING_CMD_MULTISHOT)
 
 
 /*
@@ -274,6 +343,10 @@ enum io_uring_op {
 
 /*
  * sqe->timeout_flags
+ *
+ * IORING_TIMEOUT_IMMEDIATE_ARG:	If set, sqe->addr stores the timeout
+ *					value in nanoseconds instead of
+ *					pointing to a timespec.
  */
 #define IORING_TIMEOUT_ABS		(1U << 0)
 #define IORING_TIMEOUT_UPDATE		(1U << 1)
@@ -282,6 +355,7 @@ enum io_uring_op {
 #define IORING_LINK_TIMEOUT_UPDATE	(1U << 4)
 #define IORING_TIMEOUT_ETIME_SUCCESS	(1U << 5)
 #define IORING_TIMEOUT_MULTISHOT	(1U << 6)
+#define IORING_TIMEOUT_IMMEDIATE_ARG	(1U << 7)
 #define IORING_TIMEOUT_CLOCK_MASK	(IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
 #define IORING_TIMEOUT_UPDATE_MASK	(IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
 /*
@@ -348,11 +422,24 @@ enum io_uring_op {
  *				0 is reported if zerocopy was actually possible.
  *				IORING_NOTIF_USAGE_ZC_COPIED if data was copied
  *				(at least partially).
+ *
+ * IORING_RECVSEND_BUNDLE	Used with IOSQE_BUFFER_SELECT. If set, send or
+ *				recv will grab as many buffers from the buffer
+ *				group ID given and send them all. The completion
+ *				result	will be the number of buffers send, with
+ *				the starting buffer ID in cqe->flags as per
+ *				usual for provided buffer usage. The buffers
+ *				will be	contiguous from the starting buffer ID.
+ *
+ * IORING_SEND_VECTORIZED	If set, SEND[_ZC] will take a pointer to a io_vec
+ *				to allow vectorized send operations.
  */
 #define IORING_RECVSEND_POLL_FIRST	(1U << 0)
 #define IORING_RECV_MULTISHOT		(1U << 1)
 #define IORING_RECVSEND_FIXED_BUF	(1U << 2)
 #define IORING_SEND_ZC_REPORT_USAGE	(1U << 3)
+#define IORING_RECVSEND_BUNDLE		(1U << 4)
+#define IORING_SEND_VECTORIZED		(1U << 5)
 
 /*
  * cqe.res for IORING_CQE_F_NOTIF if
@@ -367,11 +454,13 @@ enum io_uring_op {
  * accept flags stored in sqe->ioprio
  */
 #define IORING_ACCEPT_MULTISHOT	(1U << 0)
+#define IORING_ACCEPT_DONTWAIT	(1U << 1)
+#define IORING_ACCEPT_POLL_FIRST	(1U << 2)
 
 /*
  * IORING_OP_MSG_RING command types, stored in sqe->addr
  */
-enum {
+enum io_uring_msg_ring_flags {
 	IORING_MSG_DATA,	/* pass sqe->len as 'res' and off as user_data */
 	IORING_MSG_SEND_FD,	/* send a registered fd to another ring */
 };
@@ -386,11 +475,30 @@ enum {
 /* Pass through the flags from sqe->file_index to cqe->flags */
 #define IORING_MSG_RING_FLAGS_PASS	(1U << 1)
 
+/*
+ * IORING_OP_FIXED_FD_INSTALL flags (sqe->install_fd_flags)
+ *
+ * IORING_FIXED_FD_NO_CLOEXEC	Don't mark the fd as O_CLOEXEC
+ */
+#define IORING_FIXED_FD_NO_CLOEXEC	(1U << 0)
+
+/*
+ * IORING_OP_NOP flags (sqe->nop_flags)
+ *
+ * IORING_NOP_INJECT_RESULT	Inject result from sqe->result
+ */
+#define IORING_NOP_INJECT_RESULT	(1U << 0)
+#define IORING_NOP_FILE			(1U << 1)
+#define IORING_NOP_FIXED_FILE		(1U << 2)
+#define IORING_NOP_FIXED_BUFFER		(1U << 3)
+#define IORING_NOP_TW			(1U << 4)
+#define IORING_NOP_CQE32		(1U << 5)
+
 /*
  * IO completion data structure (Completion Queue Entry)
  */
 struct io_uring_cqe {
-	__u64	user_data;	/* sqe->data submission passed back */
+	__u64	user_data;	/* sqe->user_data value passed back */
 	__s32	res;		/* result code for this event */
 	__u32	flags;
 
@@ -409,15 +517,33 @@ struct io_uring_cqe {
  * IORING_CQE_F_SOCK_NONEMPTY	If set, more data to read after socket recv
  * IORING_CQE_F_NOTIF	Set for notification CQEs. Can be used to distinct
  * 			them from sends.
+ * IORING_CQE_F_BUF_MORE If set, the buffer ID set in the completion will get
+ *			more completions. In other words, the buffer is being
+ *			partially consumed, and will be used by the kernel for
+ *			more completions. This is only set for buffers used via
+ *			the incremental buffer consumption, as provided by
+ *			a ring buffer setup with IOU_PBUF_RING_INC. For any
+ *			other provided buffer type, all completions with a
+ *			buffer passed back is automatically returned to the
+ *			application.
+ * IORING_CQE_F_SKIP	If set, then the application/liburing must ignore this
+ *			CQE. It's only purpose is to fill a gap in the ring,
+ *			if a large CQE is attempted posted when the ring has
+ *			just a single small CQE worth of space left before
+ *			wrapping.
+ * IORING_CQE_F_32	If set, this is a 32b/big-cqe posting. Use with rings
+ *			setup in a mixed CQE mode, where both 16b and 32b
+ *			CQEs may be posted to the CQ ring.
  */
 #define IORING_CQE_F_BUFFER		(1U << 0)
 #define IORING_CQE_F_MORE		(1U << 1)
 #define IORING_CQE_F_SOCK_NONEMPTY	(1U << 2)
 #define IORING_CQE_F_NOTIF		(1U << 3)
+#define IORING_CQE_F_BUF_MORE		(1U << 4)
+#define IORING_CQE_F_SKIP		(1U << 5)
+#define IORING_CQE_F_32			(1U << 15)
 
-enum {
-	IORING_CQE_BUFFER_SHIFT		= 16,
-};
+#define IORING_CQE_BUFFER_SHIFT		16
 
 /*
  * Magic offsets for the application to mmap the data it needs
@@ -478,6 +604,9 @@ struct io_cqring_offsets {
 #define IORING_ENTER_SQ_WAIT		(1U << 2)
 #define IORING_ENTER_EXT_ARG		(1U << 3)
 #define IORING_ENTER_REGISTERED_RING	(1U << 4)
+#define IORING_ENTER_ABS_TIMER		(1U << 5)
+#define IORING_ENTER_EXT_ARG_REG	(1U << 6)
+#define IORING_ENTER_NO_IOWAIT		(1U << 7)
 
 /*
  * Passed in for io_uring_setup(2). Copied back with updated info on success
@@ -512,11 +641,15 @@ struct io_uring_params {
 #define IORING_FEAT_CQE_SKIP		(1U << 11)
 #define IORING_FEAT_LINKED_FILE		(1U << 12)
 #define IORING_FEAT_REG_REG_RING	(1U << 13)
+#define IORING_FEAT_RECVSEND_BUNDLE	(1U << 14)
+#define IORING_FEAT_MIN_TIMEOUT		(1U << 15)
+#define IORING_FEAT_RW_ATTR		(1U << 16)
+#define IORING_FEAT_NO_IOWAIT		(1U << 17)
 
 /*
  * io_uring_register(2) opcodes and arguments
  */
-enum {
+enum io_uring_register_op {
 	IORING_REGISTER_BUFFERS			= 0,
 	IORING_UNREGISTER_BUFFERS		= 1,
 	IORING_REGISTER_FILES			= 2,
@@ -558,6 +691,38 @@ enum {
 	/* register a range of fixed file slots for automatic slot allocation */
 	IORING_REGISTER_FILE_ALLOC_RANGE	= 25,
 
+	/* return status information for a buffer group */
+	IORING_REGISTER_PBUF_STATUS		= 26,
+
+	/* set/clear busy poll settings */
+	IORING_REGISTER_NAPI			= 27,
+	IORING_UNREGISTER_NAPI			= 28,
+
+	IORING_REGISTER_CLOCK			= 29,
+
+	/* clone registered buffers from source ring to current ring */
+	IORING_REGISTER_CLONE_BUFFERS		= 30,
+
+	/* send MSG_RING without having a ring */
+	IORING_REGISTER_SEND_MSG_RING		= 31,
+
+	/* register a netdev hw rx queue for zerocopy */
+	IORING_REGISTER_ZCRX_IFQ		= 32,
+
+	/* resize CQ ring */
+	IORING_REGISTER_RESIZE_RINGS		= 33,
+
+	IORING_REGISTER_MEM_REGION		= 34,
+
+	/* query various aspects of io_uring, see linux/io_uring/query.h */
+	IORING_REGISTER_QUERY			= 35,
+
+	/* auxiliary zcrx configuration, see enum zcrx_ctrl_op */
+	IORING_REGISTER_ZCRX_CTRL		= 36,
+
+	/* register bpf filtering programs */
+	IORING_REGISTER_BPF_FILTER		= 37,
+
 	/* this goes last */
 	IORING_REGISTER_LAST,
 
@@ -566,7 +731,7 @@ enum {
 };
 
 /* io-wq worker categories */
-enum {
+enum io_wq_type {
 	IO_WQ_BOUND,
 	IO_WQ_UNBOUND,
 };
@@ -578,6 +743,31 @@ struct io_uring_files_update {
 	__aligned_u64 /* __s32 * */ fds;
 };
 
+enum {
+	/* initialise with user provided memory pointed by user_addr */
+	IORING_MEM_REGION_TYPE_USER		= 1,
+};
+
+struct io_uring_region_desc {
+	__u64 user_addr;
+	__u64 size;
+	__u32 flags;
+	__u32 id;
+	__u64 mmap_offset;
+	__u64 __resv[4];
+};
+
+enum {
+	/* expose the region as registered wait arguments */
+	IORING_MEM_REGION_REG_WAIT_ARG		= 1,
+};
+
+struct io_uring_mem_region_reg {
+	__u64 region_uptr; /* struct io_uring_region_desc * */
+	__u64 flags;
+	__u64 __resv[2];
+};
+
 /*
  * Register a fully sparse file space, rather than pass in an array of all
  * -1 file descriptors.
@@ -638,6 +828,32 @@ struct io_uring_restriction {
 	__u32 resv2[3];
 };
 
+struct io_uring_task_restriction {
+	__u16 flags;
+	__u16 nr_res;
+	__u32 resv[3];
+	__DECLARE_FLEX_ARRAY(struct io_uring_restriction, restrictions);
+};
+
+struct io_uring_clock_register {
+	__u32	clockid;
+	__u32	__resv[3];
+};
+
+enum {
+	IORING_REGISTER_SRC_REGISTERED	= (1U << 0),
+	IORING_REGISTER_DST_REPLACE	= (1U << 1),
+};
+
+struct io_uring_clone_buffers {
+	__u32	src_fd;
+	__u32	flags;
+	__u32	src_off;
+	__u32	dst_off;
+	__u32	nr;
+	__u32	pad[3];
+};
+
 struct io_uring_buf {
 	__u64	addr;
 	__u32	len;
@@ -670,9 +886,17 @@ struct io_uring_buf_ring {
  *			mmap(2) with the offset set as:
  *			IORING_OFF_PBUF_RING | (bgid << IORING_OFF_PBUF_SHIFT)
  *			to get a virtual mapping for the ring.
+ * IOU_PBUF_RING_INC:	If set, buffers consumed from this buffer ring can be
+ *			consumed incrementally. Normally one (or more) buffers
+ *			are fully consumed. With incremental consumptions, it's
+ *			feasible to register big ranges of buffers, and each
+ *			use of it will consume only as much as it needs. This
+ *			requires that both the kernel and application keep
+ *			track of where the current read/recv index is at.
  */
-enum {
+enum io_uring_register_pbuf_ring_flags {
 	IOU_PBUF_RING_MMAP	= 1,
+	IOU_PBUF_RING_INC	= 2,
 };
 
 /* argument for IORING_(UN)REGISTER_PBUF_RING */
@@ -681,13 +905,57 @@ struct io_uring_buf_reg {
 	__u32	ring_entries;
 	__u16	bgid;
 	__u16	flags;
-	__u64	resv[3];
+	__u32	min_left;
+	__u32	resv[5];
+};
+
+/* argument for IORING_REGISTER_PBUF_STATUS */
+struct io_uring_buf_status {
+	__u32	buf_group;	/* input */
+	__u32	head;		/* output */
+	__u32	resv[8];
+};
+
+enum io_uring_napi_op {
+	/* register/ungister backward compatible opcode */
+	IO_URING_NAPI_REGISTER_OP = 0,
+
+	/* opcodes to update napi_list when static tracking is used */
+	IO_URING_NAPI_STATIC_ADD_ID = 1,
+	IO_URING_NAPI_STATIC_DEL_ID = 2
+};
+
+enum io_uring_napi_tracking_strategy {
+	/* value must be 0 for backward compatibility */
+	IO_URING_NAPI_TRACKING_DYNAMIC = 0,
+	IO_URING_NAPI_TRACKING_STATIC = 1,
+	IO_URING_NAPI_TRACKING_INACTIVE = 255
+};
+
+/* argument for IORING_(UN)REGISTER_NAPI */
+struct io_uring_napi {
+	__u32	busy_poll_to;
+	__u8	prefer_busy_poll;
+
+	/* a io_uring_napi_op value */
+	__u8	opcode;
+	__u8	pad[2];
+
+	/*
+	 * for IO_URING_NAPI_REGISTER_OP, it is a
+	 * io_uring_napi_tracking_strategy value.
+	 *
+	 * for IO_URING_NAPI_STATIC_ADD_ID/IO_URING_NAPI_STATIC_DEL_ID
+	 * it is the napi id to add/del from napi_list.
+	 */
+	__u32	op_param;
+	__u32	resv;
 };
 
 /*
  * io_uring_restriction->opcode values
  */
-enum {
+enum io_uring_register_restriction_op {
 	/* Allow an io_uring_register(2) opcode */
 	IORING_RESTRICTION_REGISTER_OP		= 0,
 
@@ -703,10 +971,33 @@ enum {
 	IORING_RESTRICTION_LAST
 };
 
+enum {
+	IORING_REG_WAIT_TS		= (1U << 0),
+};
+
+/*
+ * Argument for io_uring_enter(2) with
+ * IORING_GETEVENTS | IORING_ENTER_EXT_ARG_REG set, where the actual argument
+ * is an index into a previously registered fixed wait region described by
+ * the below structure.
+ */
+struct io_uring_reg_wait {
+	struct __kernel_timespec	ts;
+	__u32				min_wait_usec;
+	__u32				flags;
+	__u64				sigmask;
+	__u32				sigmask_sz;
+	__u32				pad[3];
+	__u64				pad2[2];
+};
+
+/*
+ * Argument for io_uring_enter(2) with IORING_GETEVENTS | IORING_ENTER_EXT_ARG
+ */
 struct io_uring_getevents_arg {
 	__u64	sigmask;
 	__u32	sigmask_sz;
-	__u32	pad;
+	__u32	min_wait_usec;
 	__u64	ts;
 };
 
@@ -743,11 +1034,28 @@ struct io_uring_recvmsg_out {
 /*
  * Argument for IORING_OP_URING_CMD when file is a socket
  */
-enum {
+enum io_uring_socket_op {
 	SOCKET_URING_OP_SIOCINQ		= 0,
 	SOCKET_URING_OP_SIOCOUTQ,
 	SOCKET_URING_OP_GETSOCKOPT,
 	SOCKET_URING_OP_SETSOCKOPT,
+	SOCKET_URING_OP_TX_TIMESTAMP,
+	SOCKET_URING_OP_GETSOCKNAME,
+};
+
+/*
+ * SOCKET_URING_OP_TX_TIMESTAMP definitions
+ */
+
+#define IORING_TIMESTAMP_HW_SHIFT	16
+/* The cqe->flags bit from which the timestamp type is stored */
+#define IORING_TIMESTAMP_TYPE_SHIFT	(IORING_TIMESTAMP_HW_SHIFT + 1)
+/* The cqe->flags flag signifying whether it's a hardware timestamp */
+#define IORING_CQE_F_TSTAMP_HW		((__u32)1 << IORING_TIMESTAMP_HW_SHIFT)
+
+struct io_timespec {
+	__u64		tv_sec;
+	__u64		tv_nsec;
 };
 
 #ifdef __cplusplus
-- 
2.47.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 2/3] fs: make file_listxattr and file_removexattr helpers non-static
  2026-09-18  9:00 [PATCH v4 0/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava
  2026-09-18  9:00 ` [PATCH v4 1/3] tools: sync io_uring.h UAPI header Aditya Prakash Srivastava
@ 2026-09-18  9:00 ` Aditya Prakash Srivastava
  2026-09-18  9:00 ` [PATCH v4 3/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava
  2 siblings, 0 replies; 5+ messages in thread
From: Aditya Prakash Srivastava @ 2026-09-18  9:00 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner, Gabriel Krisman Bertazi
  Cc: Alexander Viro, Jan Kara, io-uring, linux-fsdevel, linux-kernel,
	Aditya Prakash Srivastava

In preparation for adding IORING_OP_FREMOVEXATTR and
IORING_OP_FLISTXATTR support in io_uring, we need to invoke the VFS-layer
helpers from within io_uring.

Make the following helpers non-static and declare them in fs/internal.h:
- file_listxattr()
- file_removexattr()

No functional change is introduced.

Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
---
 fs/internal.h | 2 ++
 fs/xattr.c    | 3 +--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index c658c8a5ebd5..ff7344ac8cef 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -298,6 +298,8 @@ int filename_setxattr(int dfd, struct filename *filename,
 		      unsigned int lookup_flags, struct kernel_xattr_ctx *ctx);
 int setxattr_copy(const char __user *name, struct kernel_xattr_ctx *ctx);
 int import_xattr_name(struct xattr_name *kname, const char __user *name);
+ssize_t file_listxattr(struct file *f, char __user *list, size_t size);
+int file_removexattr(struct file *f, struct xattr_name *kname);
 
 int may_write_xattr(struct mnt_idmap *idmap, struct inode *inode);
 
diff --git a/fs/xattr.c b/fs/xattr.c
index d58979115200..31b8a5eeec1e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -953,7 +953,6 @@ listxattr(struct dentry *d, char __user *list, size_t size)
 	return error;
 }
 
-static
 ssize_t file_listxattr(struct file *f, char __user *list, size_t size)
 {
 	audit_file(f);
@@ -1036,7 +1035,7 @@ removexattr(struct mnt_idmap *idmap, struct dentry *d, const char *name)
 	return vfs_removexattr(idmap, d, name);
 }
 
-static int file_removexattr(struct file *f, struct xattr_name *kname)
+int file_removexattr(struct file *f, struct xattr_name *kname)
 {
 	int error = mnt_want_write_file(f);
 
-- 
2.47.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 3/3] io_uring: add fremovexattr and flistxattr support
  2026-09-18  9:00 [PATCH v4 0/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava
  2026-09-18  9:00 ` [PATCH v4 1/3] tools: sync io_uring.h UAPI header Aditya Prakash Srivastava
  2026-09-18  9:00 ` [PATCH v4 2/3] fs: make file_listxattr and file_removexattr helpers non-static Aditya Prakash Srivastava
@ 2026-09-18  9:00 ` Aditya Prakash Srivastava
  2 siblings, 0 replies; 5+ messages in thread
From: Aditya Prakash Srivastava @ 2026-09-18  9:00 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner, Gabriel Krisman Bertazi
  Cc: Alexander Viro, Jan Kara, io-uring, linux-fsdevel, linux-kernel,
	Aditya Prakash Srivastava

Add support for IORING_OP_FREMOVEXATTR and IORING_OP_FLISTXATTR. This
enables xattr listing and removal operations to be executed in an
asynchronous fashion.

Signed-off-by: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
---
 include/uapi/linux/io_uring.h       |  2 +
 io_uring/opdef.c                    | 18 +++++++
 io_uring/xattr.c                    | 83 +++++++++++++++++++++++++++++
 io_uring/xattr.h                    |  6 +++
 tools/include/uapi/linux/io_uring.h |  2 +
 5 files changed, 111 insertions(+)

diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 1f300f6b85d7..45de6dd6e3c4 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -318,6 +318,8 @@ enum io_uring_op {
 	IORING_OP_PIPE,
 	IORING_OP_NOP128,
 	IORING_OP_URING_CMD128,
+	IORING_OP_FREMOVEXATTR,
+	IORING_OP_FLISTXATTR,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
diff --git a/io_uring/opdef.c b/io_uring/opdef.c
index cf3aa2242cd7..14a511f7a9df 100644
--- a/io_uring/opdef.c
+++ b/io_uring/opdef.c
@@ -591,6 +591,16 @@ const struct io_issue_def io_issue_defs[] = {
 		.prep			= io_uring_cmd_prep,
 		.issue			= io_uring_cmd,
 	},
+	[IORING_OP_FREMOVEXATTR] = {
+		.needs_file		= 1,
+		.prep			= io_fremovexattr_prep,
+		.issue			= io_fremovexattr,
+	},
+	[IORING_OP_FLISTXATTR] = {
+		.needs_file		= 1,
+		.prep			= io_flistxattr_prep,
+		.issue			= io_flistxattr,
+	},
 };
 
 const struct io_cold_def io_cold_defs[] = {
@@ -849,6 +859,14 @@ const struct io_cold_def io_cold_defs[] = {
 		.sqe_copy		= io_uring_cmd_sqe_copy,
 		.cleanup		= io_uring_cmd_cleanup,
 	},
+	[IORING_OP_FREMOVEXATTR] = {
+		.name			= "FREMOVEXATTR",
+		.cleanup		= io_xattr_cleanup,
+	},
+	[IORING_OP_FLISTXATTR] = {
+		.name			= "FLISTXATTR",
+		.cleanup		= io_xattr_cleanup,
+	},
 };
 
 const char *io_uring_get_opcode(u8 opcode)
diff --git a/io_uring/xattr.c b/io_uring/xattr.c
index 5303df3f247f..f2d6b1904058 100644
--- a/io_uring/xattr.c
+++ b/io_uring/xattr.c
@@ -195,3 +195,86 @@ int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
 	io_xattr_finish(req, ret);
 	return IOU_COMPLETE;
 }
+
+int io_fremovexattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
+	const char __user *name;
+	int ret;
+
+	INIT_DELAYED_FILENAME(&ix->filename);
+	ix->ctx.kname = NULL;
+	ix->ctx.kvalue = NULL;
+
+	if (READ_ONCE(sqe->off) || READ_ONCE(sqe->addr2) || READ_ONCE(sqe->len) ||
+	    READ_ONCE(sqe->xattr_flags) || READ_ONCE(sqe->buf_index) ||
+	    READ_ONCE(sqe->splice_fd_in) || READ_ONCE(sqe->addr3) ||
+	    READ_ONCE(sqe->__pad2[0]))
+		return -EINVAL;
+
+	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
+
+	ix->ctx.kname = kmalloc_obj(*ix->ctx.kname);
+	if (!ix->ctx.kname)
+		return -ENOMEM;
+
+	ret = import_xattr_name(ix->ctx.kname, name);
+	if (ret) {
+		kfree(ix->ctx.kname);
+		ix->ctx.kname = NULL;
+		return ret;
+	}
+
+	req->flags |= REQ_F_NEED_CLEANUP;
+	req->flags |= REQ_F_FORCE_ASYNC;
+	return 0;
+}
+
+int io_fremovexattr(struct io_kiocb *req, unsigned int issue_flags)
+{
+	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
+	int ret;
+
+	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
+
+	ret = file_removexattr(req->file, ix->ctx.kname);
+	io_xattr_finish(req, ret);
+	return IOU_COMPLETE;
+}
+
+int io_flistxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
+
+	INIT_DELAYED_FILENAME(&ix->filename);
+	ix->ctx.kname = NULL;
+	ix->ctx.kvalue = NULL;
+
+	if (READ_ONCE(sqe->addr) || READ_ONCE(sqe->off) ||
+	    READ_ONCE(sqe->buf_index) || READ_ONCE(sqe->splice_fd_in) ||
+	    READ_ONCE(sqe->addr3) || READ_ONCE(sqe->__pad2[0]))
+		return -EINVAL;
+
+	ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+	ix->ctx.size = READ_ONCE(sqe->len);
+	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
+
+	if (ix->ctx.flags)
+		return -EINVAL;
+
+	req->flags |= REQ_F_NEED_CLEANUP;
+	req->flags |= REQ_F_FORCE_ASYNC;
+	return 0;
+}
+
+int io_flistxattr(struct io_kiocb *req, unsigned int issue_flags)
+{
+	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
+	int ret;
+
+	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
+
+	ret = file_listxattr(req->file, ix->ctx.value, ix->ctx.size);
+	io_xattr_finish(req, ret);
+	return IOU_COMPLETE;
+}
diff --git a/io_uring/xattr.h b/io_uring/xattr.h
index 9b459d2ae90c..d2487b49a5d2 100644
--- a/io_uring/xattr.h
+++ b/io_uring/xattr.h
@@ -13,3 +13,9 @@ int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags);
 
 int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
 int io_getxattr(struct io_kiocb *req, unsigned int issue_flags);
+
+int io_fremovexattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_fremovexattr(struct io_kiocb *req, unsigned int issue_flags);
+
+int io_flistxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_flistxattr(struct io_kiocb *req, unsigned int issue_flags);
diff --git a/tools/include/uapi/linux/io_uring.h b/tools/include/uapi/linux/io_uring.h
index 1f300f6b85d7..45de6dd6e3c4 100644
--- a/tools/include/uapi/linux/io_uring.h
+++ b/tools/include/uapi/linux/io_uring.h
@@ -318,6 +318,8 @@ enum io_uring_op {
 	IORING_OP_PIPE,
 	IORING_OP_NOP128,
 	IORING_OP_URING_CMD128,
+	IORING_OP_FREMOVEXATTR,
+	IORING_OP_FLISTXATTR,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
-- 
2.47.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 1/3] tools: sync io_uring.h UAPI header
  2026-09-18  9:00 ` [PATCH v4 1/3] tools: sync io_uring.h UAPI header Aditya Prakash Srivastava
@ 2026-09-18 16:49   ` Caleb Sander Mateos
  0 siblings, 0 replies; 5+ messages in thread
From: Caleb Sander Mateos @ 2026-09-18 16:49 UTC (permalink / raw)
  To: Aditya Prakash Srivastava
  Cc: Jens Axboe, Christian Brauner, Gabriel Krisman Bertazi,
	Alexander Viro, Jan Kara, io-uring, linux-fsdevel, linux-kernel

On Fri, Sep 18, 2026 at 2:16 AM Aditya Prakash Srivastava
<aditya.ansh182@gmail.com> wrote:
>
> Sync tools/include/uapi/linux/io_uring.h with the main kernel
> include/uapi/linux/io_uring.h UAPI header to ensure they are
> perfectly aligned.
>
> Additionally, correct a minor space-before-tab checkpatch.pl warning
> in the comments of both headers (no functional change).
>
> Suggested-by: Gabriel Krisman Bertazi <krisman@suse.de>
> Signed-off-by: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
> ---
>  include/uapi/linux/io_uring.h       |   2 +-
>  tools/include/uapi/linux/io_uring.h | 340 ++++++++++++++++++++++++++--
>  2 files changed, 325 insertions(+), 17 deletions(-)
>
> diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
> index 909fb7aea638..1f300f6b85d7 100644
> --- a/include/uapi/linux/io_uring.h
> +++ b/include/uapi/linux/io_uring.h
> @@ -426,7 +426,7 @@ enum io_uring_op {
>   * IORING_RECVSEND_BUNDLE      Used with IOSQE_BUFFER_SELECT. If set, send or
>   *                             recv will grab as many buffers from the buffer
>   *                             group ID given and send them all. The completion
> - *                             result  will be the number of buffers send, with
> + *                             result  will be the number of buffers send, with

Can you drop the tab character and just use a space between the words?

Best,
Caleb

>   *                             the starting buffer ID in cqe->flags as per
>   *                             usual for provided buffer usage. The buffers
>   *                             will be contiguous from the starting buffer ID.
> diff --git a/tools/include/uapi/linux/io_uring.h b/tools/include/uapi/linux/io_uring.h
> index f1c16f817742..1f300f6b85d7 100644
> --- a/tools/include/uapi/linux/io_uring.h
> +++ b/tools/include/uapi/linux/io_uring.h
> @@ -10,6 +10,8 @@
>
>  #include <linux/fs.h>
>  #include <linux/types.h>
> +#include <linux/io_uring/zcrx.h>
> +
>  /*
>   * this file is shared with liburing and that has to autodetect
>   * if linux/time_types.h is available or not, it can
> @@ -50,7 +52,7 @@ struct io_uring_sqe {
>         };
>         __u32   len;            /* buffer size or number of iovecs */
>         union {
> -               __kernel_rwf_t  rw_flags;
> +               __u32           rw_flags;
>                 __u32           fsync_flags;
>                 __u16           poll_events;    /* compatibility */
>                 __u32           poll32_events;  /* word-reversed for BE */
> @@ -71,6 +73,9 @@ struct io_uring_sqe {
>                 __u32           uring_cmd_flags;
>                 __u32           waitid_flags;
>                 __u32           futex_flags;
> +               __u32           install_fd_flags;
> +               __u32           nop_flags;
> +               __u32           pipe_flags;
>         };
>         __u64   user_data;      /* data to be passed back at completion time */
>         /* pack this to avoid bogus arm OABI complaints */
> @@ -85,17 +90,26 @@ struct io_uring_sqe {
>         union {
>                 __s32   splice_fd_in;
>                 __u32   file_index;
> +               __u32   zcrx_ifq_idx;
>                 __u32   optlen;
>                 struct {
>                         __u16   addr_len;
>                         __u16   __pad3[1];
>                 };
> +               struct {
> +                       __u8    write_stream;
> +                       __u8    __pad4[3];
> +               };
>         };
>         union {
>                 struct {
>                         __u64   addr3;
>                         __u64   __pad2[1];
>                 };
> +               struct {
> +                       __u64   attr_ptr; /* pointer to attribute information */
> +                       __u64   attr_type_mask; /* bit mask of attributes */
> +               };
>                 __u64   optval;
>                 /*
>                  * If the ring is initialized with IORING_SETUP_SQE128, then
> @@ -105,6 +119,18 @@ struct io_uring_sqe {
>         };
>  };
>
> +/* sqe->attr_type_mask flags */
> +#define IORING_RW_ATTR_FLAG_PI (1U << 0)
> +/* PI attribute information */
> +struct io_uring_attr_pi {
> +               __u16   flags;
> +               __u16   app_tag;
> +               __u32   len;
> +               __u64   addr;
> +               __u64   seed;
> +               __u64   rsvd;
> +};
> +
>  /*
>   * If sqe->file_index is set to this for opcodes that instantiate a new
>   * direct descriptor (like openat/openat2/accept), then io_uring will allocate
> @@ -114,7 +140,7 @@ struct io_uring_sqe {
>   */
>  #define IORING_FILE_INDEX_ALLOC                (~0U)
>
> -enum {
> +enum io_uring_sqe_flags_bit {
>         IOSQE_FIXED_FILE_BIT,
>         IOSQE_IO_DRAIN_BIT,
>         IOSQE_IO_LINK_BIT,
> @@ -164,7 +190,8 @@ enum {
>  /*
>   * If COOP_TASKRUN is set, get notified if task work is available for
>   * running and a kernel transition would be needed to run it. This sets
> - * IORING_SQ_TASKRUN in the sq ring flags. Not valid with COOP_TASKRUN.
> + * IORING_SQ_TASKRUN in the sq ring flags. Not valid without COOP_TASKRUN
> + * or DEFER_TASKRUN.
>   */
>  #define IORING_SETUP_TASKRUN_FLAG      (1U << 9)
>  #define IORING_SETUP_SQE128            (1U << 10) /* SQEs are 128 byte */
> @@ -198,6 +225,33 @@ enum {
>   */
>  #define IORING_SETUP_NO_SQARRAY                (1U << 16)
>
> +/* Use hybrid poll in iopoll process */
> +#define IORING_SETUP_HYBRID_IOPOLL     (1U << 17)
> +
> +/*
> + * Allow both 16b and 32b CQEs. If a 32b CQE is posted, it will have
> + * IORING_CQE_F_32 set in cqe->flags.
> + */
> +#define IORING_SETUP_CQE_MIXED         (1U << 18)
> +
> +/*
> + * Allow both 64b and 128b SQEs. If a 128b SQE is posted, it will have
> + * a 128b opcode.
> + */
> +#define IORING_SETUP_SQE_MIXED         (1U << 19)
> +
> +/*
> + * When set, io_uring ignores SQ head and tail and fetches SQEs to submit
> + * starting from index 0 instead from the index stored in the head pointer.
> + * IOW, the user should place all SQE at the beginning of the SQ memory
> + * before issuing a submission syscall.
> + *
> + * It requires IORING_SETUP_NO_SQARRAY and is incompatible with
> + * IORING_SETUP_SQPOLL. The user must also never change the SQ head and tail
> + * values and keep it set to 0. Any other value is undefined behaviour.
> + */
> +#define IORING_SETUP_SQ_REWIND         (1U << 20)
> +
>  enum io_uring_op {
>         IORING_OP_NOP,
>         IORING_OP_READV,
> @@ -253,6 +307,17 @@ enum io_uring_op {
>         IORING_OP_FUTEX_WAIT,
>         IORING_OP_FUTEX_WAKE,
>         IORING_OP_FUTEX_WAITV,
> +       IORING_OP_FIXED_FD_INSTALL,
> +       IORING_OP_FTRUNCATE,
> +       IORING_OP_BIND,
> +       IORING_OP_LISTEN,
> +       IORING_OP_RECV_ZC,
> +       IORING_OP_EPOLL_WAIT,
> +       IORING_OP_READV_FIXED,
> +       IORING_OP_WRITEV_FIXED,
> +       IORING_OP_PIPE,
> +       IORING_OP_NOP128,
> +       IORING_OP_URING_CMD128,
>
>         /* this goes last, obviously */
>         IORING_OP_LAST,
> @@ -262,9 +327,13 @@ enum io_uring_op {
>   * sqe->uring_cmd_flags                top 8bits aren't available for userspace
>   * IORING_URING_CMD_FIXED      use registered buffer; pass this flag
>   *                             along with setting sqe->buf_index.
> + * IORING_URING_CMD_MULTISHOT  must be used with buffer select, like other
> + *                             multishot commands. Not compatible with
> + *                             IORING_URING_CMD_FIXED, for now.
>   */
>  #define IORING_URING_CMD_FIXED (1U << 0)
> -#define IORING_URING_CMD_MASK  IORING_URING_CMD_FIXED
> +#define IORING_URING_CMD_MULTISHOT     (1U << 1)
> +#define IORING_URING_CMD_MASK  (IORING_URING_CMD_FIXED | IORING_URING_CMD_MULTISHOT)
>
>
>  /*
> @@ -274,6 +343,10 @@ enum io_uring_op {
>
>  /*
>   * sqe->timeout_flags
> + *
> + * IORING_TIMEOUT_IMMEDIATE_ARG:       If set, sqe->addr stores the timeout
> + *                                     value in nanoseconds instead of
> + *                                     pointing to a timespec.
>   */
>  #define IORING_TIMEOUT_ABS             (1U << 0)
>  #define IORING_TIMEOUT_UPDATE          (1U << 1)
> @@ -282,6 +355,7 @@ enum io_uring_op {
>  #define IORING_LINK_TIMEOUT_UPDATE     (1U << 4)
>  #define IORING_TIMEOUT_ETIME_SUCCESS   (1U << 5)
>  #define IORING_TIMEOUT_MULTISHOT       (1U << 6)
> +#define IORING_TIMEOUT_IMMEDIATE_ARG   (1U << 7)
>  #define IORING_TIMEOUT_CLOCK_MASK      (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
>  #define IORING_TIMEOUT_UPDATE_MASK     (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
>  /*
> @@ -348,11 +422,24 @@ enum io_uring_op {
>   *                             0 is reported if zerocopy was actually possible.
>   *                             IORING_NOTIF_USAGE_ZC_COPIED if data was copied
>   *                             (at least partially).
> + *
> + * IORING_RECVSEND_BUNDLE      Used with IOSQE_BUFFER_SELECT. If set, send or
> + *                             recv will grab as many buffers from the buffer
> + *                             group ID given and send them all. The completion
> + *                             result  will be the number of buffers send, with
> + *                             the starting buffer ID in cqe->flags as per
> + *                             usual for provided buffer usage. The buffers
> + *                             will be contiguous from the starting buffer ID.
> + *
> + * IORING_SEND_VECTORIZED      If set, SEND[_ZC] will take a pointer to a io_vec
> + *                             to allow vectorized send operations.
>   */
>  #define IORING_RECVSEND_POLL_FIRST     (1U << 0)
>  #define IORING_RECV_MULTISHOT          (1U << 1)
>  #define IORING_RECVSEND_FIXED_BUF      (1U << 2)
>  #define IORING_SEND_ZC_REPORT_USAGE    (1U << 3)
> +#define IORING_RECVSEND_BUNDLE         (1U << 4)
> +#define IORING_SEND_VECTORIZED         (1U << 5)
>
>  /*
>   * cqe.res for IORING_CQE_F_NOTIF if
> @@ -367,11 +454,13 @@ enum io_uring_op {
>   * accept flags stored in sqe->ioprio
>   */
>  #define IORING_ACCEPT_MULTISHOT        (1U << 0)
> +#define IORING_ACCEPT_DONTWAIT (1U << 1)
> +#define IORING_ACCEPT_POLL_FIRST       (1U << 2)
>
>  /*
>   * IORING_OP_MSG_RING command types, stored in sqe->addr
>   */
> -enum {
> +enum io_uring_msg_ring_flags {
>         IORING_MSG_DATA,        /* pass sqe->len as 'res' and off as user_data */
>         IORING_MSG_SEND_FD,     /* send a registered fd to another ring */
>  };
> @@ -386,11 +475,30 @@ enum {
>  /* Pass through the flags from sqe->file_index to cqe->flags */
>  #define IORING_MSG_RING_FLAGS_PASS     (1U << 1)
>
> +/*
> + * IORING_OP_FIXED_FD_INSTALL flags (sqe->install_fd_flags)
> + *
> + * IORING_FIXED_FD_NO_CLOEXEC  Don't mark the fd as O_CLOEXEC
> + */
> +#define IORING_FIXED_FD_NO_CLOEXEC     (1U << 0)
> +
> +/*
> + * IORING_OP_NOP flags (sqe->nop_flags)
> + *
> + * IORING_NOP_INJECT_RESULT    Inject result from sqe->result
> + */
> +#define IORING_NOP_INJECT_RESULT       (1U << 0)
> +#define IORING_NOP_FILE                        (1U << 1)
> +#define IORING_NOP_FIXED_FILE          (1U << 2)
> +#define IORING_NOP_FIXED_BUFFER                (1U << 3)
> +#define IORING_NOP_TW                  (1U << 4)
> +#define IORING_NOP_CQE32               (1U << 5)
> +
>  /*
>   * IO completion data structure (Completion Queue Entry)
>   */
>  struct io_uring_cqe {
> -       __u64   user_data;      /* sqe->data submission passed back */
> +       __u64   user_data;      /* sqe->user_data value passed back */
>         __s32   res;            /* result code for this event */
>         __u32   flags;
>
> @@ -409,15 +517,33 @@ struct io_uring_cqe {
>   * IORING_CQE_F_SOCK_NONEMPTY  If set, more data to read after socket recv
>   * IORING_CQE_F_NOTIF  Set for notification CQEs. Can be used to distinct
>   *                     them from sends.
> + * IORING_CQE_F_BUF_MORE If set, the buffer ID set in the completion will get
> + *                     more completions. In other words, the buffer is being
> + *                     partially consumed, and will be used by the kernel for
> + *                     more completions. This is only set for buffers used via
> + *                     the incremental buffer consumption, as provided by
> + *                     a ring buffer setup with IOU_PBUF_RING_INC. For any
> + *                     other provided buffer type, all completions with a
> + *                     buffer passed back is automatically returned to the
> + *                     application.
> + * IORING_CQE_F_SKIP   If set, then the application/liburing must ignore this
> + *                     CQE. It's only purpose is to fill a gap in the ring,
> + *                     if a large CQE is attempted posted when the ring has
> + *                     just a single small CQE worth of space left before
> + *                     wrapping.
> + * IORING_CQE_F_32     If set, this is a 32b/big-cqe posting. Use with rings
> + *                     setup in a mixed CQE mode, where both 16b and 32b
> + *                     CQEs may be posted to the CQ ring.
>   */
>  #define IORING_CQE_F_BUFFER            (1U << 0)
>  #define IORING_CQE_F_MORE              (1U << 1)
>  #define IORING_CQE_F_SOCK_NONEMPTY     (1U << 2)
>  #define IORING_CQE_F_NOTIF             (1U << 3)
> +#define IORING_CQE_F_BUF_MORE          (1U << 4)
> +#define IORING_CQE_F_SKIP              (1U << 5)
> +#define IORING_CQE_F_32                        (1U << 15)
>
> -enum {
> -       IORING_CQE_BUFFER_SHIFT         = 16,
> -};
> +#define IORING_CQE_BUFFER_SHIFT                16
>
>  /*
>   * Magic offsets for the application to mmap the data it needs
> @@ -478,6 +604,9 @@ struct io_cqring_offsets {
>  #define IORING_ENTER_SQ_WAIT           (1U << 2)
>  #define IORING_ENTER_EXT_ARG           (1U << 3)
>  #define IORING_ENTER_REGISTERED_RING   (1U << 4)
> +#define IORING_ENTER_ABS_TIMER         (1U << 5)
> +#define IORING_ENTER_EXT_ARG_REG       (1U << 6)
> +#define IORING_ENTER_NO_IOWAIT         (1U << 7)
>
>  /*
>   * Passed in for io_uring_setup(2). Copied back with updated info on success
> @@ -512,11 +641,15 @@ struct io_uring_params {
>  #define IORING_FEAT_CQE_SKIP           (1U << 11)
>  #define IORING_FEAT_LINKED_FILE                (1U << 12)
>  #define IORING_FEAT_REG_REG_RING       (1U << 13)
> +#define IORING_FEAT_RECVSEND_BUNDLE    (1U << 14)
> +#define IORING_FEAT_MIN_TIMEOUT                (1U << 15)
> +#define IORING_FEAT_RW_ATTR            (1U << 16)
> +#define IORING_FEAT_NO_IOWAIT          (1U << 17)
>
>  /*
>   * io_uring_register(2) opcodes and arguments
>   */
> -enum {
> +enum io_uring_register_op {
>         IORING_REGISTER_BUFFERS                 = 0,
>         IORING_UNREGISTER_BUFFERS               = 1,
>         IORING_REGISTER_FILES                   = 2,
> @@ -558,6 +691,38 @@ enum {
>         /* register a range of fixed file slots for automatic slot allocation */
>         IORING_REGISTER_FILE_ALLOC_RANGE        = 25,
>
> +       /* return status information for a buffer group */
> +       IORING_REGISTER_PBUF_STATUS             = 26,
> +
> +       /* set/clear busy poll settings */
> +       IORING_REGISTER_NAPI                    = 27,
> +       IORING_UNREGISTER_NAPI                  = 28,
> +
> +       IORING_REGISTER_CLOCK                   = 29,
> +
> +       /* clone registered buffers from source ring to current ring */
> +       IORING_REGISTER_CLONE_BUFFERS           = 30,
> +
> +       /* send MSG_RING without having a ring */
> +       IORING_REGISTER_SEND_MSG_RING           = 31,
> +
> +       /* register a netdev hw rx queue for zerocopy */
> +       IORING_REGISTER_ZCRX_IFQ                = 32,
> +
> +       /* resize CQ ring */
> +       IORING_REGISTER_RESIZE_RINGS            = 33,
> +
> +       IORING_REGISTER_MEM_REGION              = 34,
> +
> +       /* query various aspects of io_uring, see linux/io_uring/query.h */
> +       IORING_REGISTER_QUERY                   = 35,
> +
> +       /* auxiliary zcrx configuration, see enum zcrx_ctrl_op */
> +       IORING_REGISTER_ZCRX_CTRL               = 36,
> +
> +       /* register bpf filtering programs */
> +       IORING_REGISTER_BPF_FILTER              = 37,
> +
>         /* this goes last */
>         IORING_REGISTER_LAST,
>
> @@ -566,7 +731,7 @@ enum {
>  };
>
>  /* io-wq worker categories */
> -enum {
> +enum io_wq_type {
>         IO_WQ_BOUND,
>         IO_WQ_UNBOUND,
>  };
> @@ -578,6 +743,31 @@ struct io_uring_files_update {
>         __aligned_u64 /* __s32 * */ fds;
>  };
>
> +enum {
> +       /* initialise with user provided memory pointed by user_addr */
> +       IORING_MEM_REGION_TYPE_USER             = 1,
> +};
> +
> +struct io_uring_region_desc {
> +       __u64 user_addr;
> +       __u64 size;
> +       __u32 flags;
> +       __u32 id;
> +       __u64 mmap_offset;
> +       __u64 __resv[4];
> +};
> +
> +enum {
> +       /* expose the region as registered wait arguments */
> +       IORING_MEM_REGION_REG_WAIT_ARG          = 1,
> +};
> +
> +struct io_uring_mem_region_reg {
> +       __u64 region_uptr; /* struct io_uring_region_desc * */
> +       __u64 flags;
> +       __u64 __resv[2];
> +};
> +
>  /*
>   * Register a fully sparse file space, rather than pass in an array of all
>   * -1 file descriptors.
> @@ -638,6 +828,32 @@ struct io_uring_restriction {
>         __u32 resv2[3];
>  };
>
> +struct io_uring_task_restriction {
> +       __u16 flags;
> +       __u16 nr_res;
> +       __u32 resv[3];
> +       __DECLARE_FLEX_ARRAY(struct io_uring_restriction, restrictions);
> +};
> +
> +struct io_uring_clock_register {
> +       __u32   clockid;
> +       __u32   __resv[3];
> +};
> +
> +enum {
> +       IORING_REGISTER_SRC_REGISTERED  = (1U << 0),
> +       IORING_REGISTER_DST_REPLACE     = (1U << 1),
> +};
> +
> +struct io_uring_clone_buffers {
> +       __u32   src_fd;
> +       __u32   flags;
> +       __u32   src_off;
> +       __u32   dst_off;
> +       __u32   nr;
> +       __u32   pad[3];
> +};
> +
>  struct io_uring_buf {
>         __u64   addr;
>         __u32   len;
> @@ -670,9 +886,17 @@ struct io_uring_buf_ring {
>   *                     mmap(2) with the offset set as:
>   *                     IORING_OFF_PBUF_RING | (bgid << IORING_OFF_PBUF_SHIFT)
>   *                     to get a virtual mapping for the ring.
> + * IOU_PBUF_RING_INC:  If set, buffers consumed from this buffer ring can be
> + *                     consumed incrementally. Normally one (or more) buffers
> + *                     are fully consumed. With incremental consumptions, it's
> + *                     feasible to register big ranges of buffers, and each
> + *                     use of it will consume only as much as it needs. This
> + *                     requires that both the kernel and application keep
> + *                     track of where the current read/recv index is at.
>   */
> -enum {
> +enum io_uring_register_pbuf_ring_flags {
>         IOU_PBUF_RING_MMAP      = 1,
> +       IOU_PBUF_RING_INC       = 2,
>  };
>
>  /* argument for IORING_(UN)REGISTER_PBUF_RING */
> @@ -681,13 +905,57 @@ struct io_uring_buf_reg {
>         __u32   ring_entries;
>         __u16   bgid;
>         __u16   flags;
> -       __u64   resv[3];
> +       __u32   min_left;
> +       __u32   resv[5];
> +};
> +
> +/* argument for IORING_REGISTER_PBUF_STATUS */
> +struct io_uring_buf_status {
> +       __u32   buf_group;      /* input */
> +       __u32   head;           /* output */
> +       __u32   resv[8];
> +};
> +
> +enum io_uring_napi_op {
> +       /* register/ungister backward compatible opcode */
> +       IO_URING_NAPI_REGISTER_OP = 0,
> +
> +       /* opcodes to update napi_list when static tracking is used */
> +       IO_URING_NAPI_STATIC_ADD_ID = 1,
> +       IO_URING_NAPI_STATIC_DEL_ID = 2
> +};
> +
> +enum io_uring_napi_tracking_strategy {
> +       /* value must be 0 for backward compatibility */
> +       IO_URING_NAPI_TRACKING_DYNAMIC = 0,
> +       IO_URING_NAPI_TRACKING_STATIC = 1,
> +       IO_URING_NAPI_TRACKING_INACTIVE = 255
> +};
> +
> +/* argument for IORING_(UN)REGISTER_NAPI */
> +struct io_uring_napi {
> +       __u32   busy_poll_to;
> +       __u8    prefer_busy_poll;
> +
> +       /* a io_uring_napi_op value */
> +       __u8    opcode;
> +       __u8    pad[2];
> +
> +       /*
> +        * for IO_URING_NAPI_REGISTER_OP, it is a
> +        * io_uring_napi_tracking_strategy value.
> +        *
> +        * for IO_URING_NAPI_STATIC_ADD_ID/IO_URING_NAPI_STATIC_DEL_ID
> +        * it is the napi id to add/del from napi_list.
> +        */
> +       __u32   op_param;
> +       __u32   resv;
>  };
>
>  /*
>   * io_uring_restriction->opcode values
>   */
> -enum {
> +enum io_uring_register_restriction_op {
>         /* Allow an io_uring_register(2) opcode */
>         IORING_RESTRICTION_REGISTER_OP          = 0,
>
> @@ -703,10 +971,33 @@ enum {
>         IORING_RESTRICTION_LAST
>  };
>
> +enum {
> +       IORING_REG_WAIT_TS              = (1U << 0),
> +};
> +
> +/*
> + * Argument for io_uring_enter(2) with
> + * IORING_GETEVENTS | IORING_ENTER_EXT_ARG_REG set, where the actual argument
> + * is an index into a previously registered fixed wait region described by
> + * the below structure.
> + */
> +struct io_uring_reg_wait {
> +       struct __kernel_timespec        ts;
> +       __u32                           min_wait_usec;
> +       __u32                           flags;
> +       __u64                           sigmask;
> +       __u32                           sigmask_sz;
> +       __u32                           pad[3];
> +       __u64                           pad2[2];
> +};
> +
> +/*
> + * Argument for io_uring_enter(2) with IORING_GETEVENTS | IORING_ENTER_EXT_ARG
> + */
>  struct io_uring_getevents_arg {
>         __u64   sigmask;
>         __u32   sigmask_sz;
> -       __u32   pad;
> +       __u32   min_wait_usec;
>         __u64   ts;
>  };
>
> @@ -743,11 +1034,28 @@ struct io_uring_recvmsg_out {
>  /*
>   * Argument for IORING_OP_URING_CMD when file is a socket
>   */
> -enum {
> +enum io_uring_socket_op {
>         SOCKET_URING_OP_SIOCINQ         = 0,
>         SOCKET_URING_OP_SIOCOUTQ,
>         SOCKET_URING_OP_GETSOCKOPT,
>         SOCKET_URING_OP_SETSOCKOPT,
> +       SOCKET_URING_OP_TX_TIMESTAMP,
> +       SOCKET_URING_OP_GETSOCKNAME,
> +};
> +
> +/*
> + * SOCKET_URING_OP_TX_TIMESTAMP definitions
> + */
> +
> +#define IORING_TIMESTAMP_HW_SHIFT      16
> +/* The cqe->flags bit from which the timestamp type is stored */
> +#define IORING_TIMESTAMP_TYPE_SHIFT    (IORING_TIMESTAMP_HW_SHIFT + 1)
> +/* The cqe->flags flag signifying whether it's a hardware timestamp */
> +#define IORING_CQE_F_TSTAMP_HW         ((__u32)1 << IORING_TIMESTAMP_HW_SHIFT)
> +
> +struct io_timespec {
> +       __u64           tv_sec;
> +       __u64           tv_nsec;
>  };
>
>  #ifdef __cplusplus
> --
> 2.47.3
>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-18 16:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-18  9:00 [PATCH v4 0/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava
2026-09-18  9:00 ` [PATCH v4 1/3] tools: sync io_uring.h UAPI header Aditya Prakash Srivastava
2026-09-18 16:49   ` Caleb Sander Mateos
2026-09-18  9:00 ` [PATCH v4 2/3] fs: make file_listxattr and file_removexattr helpers non-static Aditya Prakash Srivastava
2026-09-18  9:00 ` [PATCH v4 3/3] io_uring: add fremovexattr and flistxattr support Aditya Prakash Srivastava

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®