All of lore.kernel.org
 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; 7+ 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] 7+ 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; 7+ 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 related	[flat|nested] 7+ 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; 7+ 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 related	[flat|nested] 7+ 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; 7+ 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 related	[flat|nested] 7+ 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
  2026-10-01 10:58     ` Aditya Prakash Srivastava
  0 siblings, 1 reply; 7+ 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] 7+ messages in thread

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

On Fri, Sep 18, 2026 at 10:20 PM Caleb Sander Mateos
<csander@purestorage.com> wrote:
>
> Can you drop the tab character and just use a space between the words?
>
> Best,
> Caleb
>
Thanks Caleb, will fix that to use a single space in the next revision.

Hi Jens, Gabriel,

If there are no other comments or concerns with the patch series, I
can send v5 with Caleb's formatting fix addressed. If there are further
changes needed, I can pick them up in v5 along with Caleb's space
suggestion.

Thanks,
Aditya

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

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

Aditya Prakash Srivastava <aditya.ansh182@gmail.com> writes:

> On Fri, Sep 18, 2026 at 10:20 PM Caleb Sander Mateos
> <csander@purestorage.com> wrote:
>>
>> Can you drop the tab character and just use a space between the words?
>>
>> Best,
>> Caleb
>>
> Thanks Caleb, will fix that to use a single space in the next revision.
>
> Hi Jens, Gabriel,
>
> If there are no other comments or concerns with the patch series, I
> can send v5 with Caleb's formatting fix addressed. If there are further
> changes needed, I can pick them up in v5 along with Caleb's space
> suggestion.

I don't have further comments. As I mentioned in a previous review, Jens
pointed out pushing to the io-wq is not the best design, but we don't
have the infrastructure to do it in a different way yet.

-- 
Gabriel Krisman Bertazi

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

end of thread, other threads:[~2026-10-01 15:40 UTC | newest]

Thread overview: 7+ 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-10-01 10:58     ` Aditya Prakash Srivastava
2026-10-01 15:40       ` Gabriel Krisman Bertazi
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.