strat9_kernel/async_io/ops.rs
1//! Asynchronous I/O ABI types : stable across kernel versions.
2//!
3//! Defines the [`AsyncOp`] opcode enum, [`AsyncSqe`] (submission queue entry),
4//! and [`AsyncCqe`] (completion queue event) as `#[repr(C)]` structs.
5
6/// Operation opcode submitted through the async ring.
7///
8/// **Do not reorder** existing variants : the numeric value is part of the
9/// userspace ABI and must remain stable.
10#[repr(u8)]
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[allow(dead_code)]
13pub enum AsyncOp {
14 /// No-op : used for testing and ring probing.
15 Nop = 0,
16 /// VFS: read from an open file descriptor.
17 Read = 1,
18 /// VFS: write to an open file descriptor.
19 Write = 2,
20 /// VFS: open a file (async version).
21 Open = 3,
22 /// VFS: close a file descriptor.
23 Close = 4,
24 /// VFS: stat / fstat a file.
25 Stat = 5,
26
27 /// IPC: send a message to a port (non-blocking).
28 IpcSend = 10,
29 /// IPC: receive a message from a port (non-blocking).
30 IpcRecv = 11,
31 /// IPC: combined send + recv (reply channel).
32 IpcCall = 12,
33
34 /// Poll: add an fd to the epoll set.
35 PollAdd = 20,
36 /// Poll: remove an fd from the epoll set.
37 PollRemove = 21,
38
39 /// Timer: arm a timeout completion.
40 Timeout = 30,
41 /// Timer: remove a previously armed timeout.
42 TimeoutRemove = 31,
43
44 /// Network: accept a connection on a listening socket.
45 Accept = 40,
46 /// Network: connect to a remote endpoint.
47 Connect = 41,
48
49 /// Storage: read sectors from a block device (AHCI / NVMe).
50 StorageRead = 50,
51 /// Storage: write sectors to a block device.
52 StorageWrite = 51,
53
54 /// Cancel an in-flight operation by its `user_data` token.
55 Cancel = 254,
56}
57
58// =============================================================================
59// SQE : Submission Queue Entry (64 bytes, cache-line aligned)
60// =============================================================================
61
62/// A single I/O submission, written by userspace into the SQ ring.
63#[repr(C)]
64#[derive(Debug, Clone, Copy)]
65pub struct AsyncSqe {
66 /// Operation opcode ([`AsyncOp`] variant).
67 pub opcode: u8,
68 /// Flags: `FIXED_FILE`, `IO_LINK`, `IO_DRAIN`, `IO_HARDLINK`.
69 pub flags: u8,
70 /// Priority hint (ioprio class << 13 | ioprio data).
71 pub ioprio: u16,
72 /// File descriptor (VFS fd) or IPC port id.
73 pub fd: u32,
74 /// File offset (for read/write) or endpoint id (for IPC).
75 pub off: u64,
76 /// Buffer virtual address (userspace pointer : validated by kernel).
77 pub addr: u64,
78 /// Buffer length in bytes.
79 pub len: u32,
80 /// Operation-specific flags (e.g. `RW_FSYNC` for write).
81 pub op_flags: u32,
82 /// Opaque correlation token : echoed in the CQE on completion.
83 pub user_data: u64,
84 /// Personality / capability context (silo token).
85 pub personality: u16,
86 /// Padding to 64 bytes (cache-line aligned).
87 pub _pad: [u8; 22],
88}
89
90// Compile-time size check : must be exactly 64 bytes.
91const _: () = assert!(core::mem::size_of::<AsyncSqe>() == 64);
92
93// =============================================================================
94// CQE : Completion Queue Event (16 bytes)
95// =============================================================================
96
97/// A single I/O completion, written by the kernel into the CQ ring.
98#[repr(C)]
99#[derive(Debug, Clone, Copy)]
100pub struct AsyncCqe {
101 /// Opaque correlation token from the originating SQE.
102 pub user_data: u64,
103 /// Result: bytes transferred on success, or a negative errno on failure.
104 pub res: i32,
105 /// Flags: `CQE_F_BUFFER`, `CQE_F_MORE`.
106 pub flags: u32,
107}
108
109// Compile-time size check : must be exactly 16 bytes.
110const _: () = assert!(core::mem::size_of::<AsyncCqe>() == 16);
111
112// =============================================================================
113// Shared constants
114// =============================================================================
115
116/// Maximum number of in-flight operations per ring.
117pub const MAX_IN_FLIGHT: usize = 4096;
118
119/// Default SQE ring size (must be a power of two).
120pub const DEFAULT_RING_ENTRIES: u32 = 256;