* [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.