Skip to content

Commit e40e539

Browse files
committed
add msg_ring_*, setxattr and getxattr IoUring operations
TODO: add SetXattr flags Signed-off-by: Bernard Assan <[email protected]>
1 parent 0caafe3 commit e40e539

File tree

2 files changed

+244
-0
lines changed

2 files changed

+244
-0
lines changed

lib/std/os/linux.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6845,6 +6845,9 @@ pub const Rename = packed struct(u32) {
68456845
_: u29 = 0,
68466846
};
68476847

6848+
pub const SetXattr = packed struct(u32) {
6849+
_: u32 = 0, // TODO: add flags
6850+
};
68486851
pub const statx_timestamp = extern struct {
68496852
sec: i64,
68506853
nsec: u32,

lib/std/os/linux/IoUring.zig

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,137 @@ pub fn link(
15161516
return try self.linkat(user_data, linux.At.fdcwd, old_path, linux.At.fdcwd, new_path, flags);
15171517
}
15181518

1519+
/// Queues (but does not submit) an SQE to send a CQE to an io_uring file
1520+
/// descriptor. The use case for this can be anything from simply waking up
1521+
/// someone waiting on the targeted ring, or it can be used to pass messages
1522+
/// between the two rings
1523+
/// Returns a pointer to the SQE.
1524+
pub fn msg_ring(
1525+
self: *IoUring,
1526+
user_data: u64,
1527+
fd: linux.fd_t,
1528+
len: u32,
1529+
data: u64,
1530+
flags: uflags.MsgRing,
1531+
) !*Sqe {
1532+
const sqe = try self.get_sqe();
1533+
sqe.prep_msg_ring(fd, len, data, flags);
1534+
sqe.user_data = user_data;
1535+
return sqe;
1536+
}
1537+
1538+
/// Queues (but does not submit) an SQE to send a CQE to an io_uring file
1539+
/// descriptor. See `msg_ring`
1540+
/// This has and additonal `cqe_flags` parameter that allows you to set the CQE
1541+
/// flags field cqe.flags when sending a message
1542+
/// Returns a pointer to the SQE.
1543+
pub fn msg_ring_cqe_flags(
1544+
self: *IoUring,
1545+
user_data: u64,
1546+
fd: linux.fd_t,
1547+
len: u32,
1548+
data: u64,
1549+
msg_flags: uflags.MsgRing,
1550+
cqe_flags: Cqe.Flags,
1551+
) !*Sqe {
1552+
const sqe = try self.get_sqe();
1553+
sqe.prep_msg_ring_cqe_flags(
1554+
fd,
1555+
len,
1556+
data,
1557+
msg_flags,
1558+
cqe_flags,
1559+
);
1560+
sqe.user_data = user_data;
1561+
return sqe;
1562+
}
1563+
1564+
/// Queues (but does not submit) an SQE to to send a direct file descriptor to
1565+
/// another ring.
1566+
/// This has and additonal `cqe_flags` parameter that allows you to set the CQE
1567+
/// flags field cqe.flags when sending a message
1568+
/// Returns a pointer to the SQE.
1569+
pub fn msg_ring_fd(
1570+
self: *IoUring,
1571+
user_data: u64,
1572+
fd: linux.fd_t,
1573+
source_fd: linux.fd_t,
1574+
target_fd: linux.fd_t,
1575+
data: u64,
1576+
flags: uflags.MsgRing,
1577+
) !*Sqe {
1578+
const sqe = try self.get_sqe();
1579+
sqe.prep_msg_ring_fd(
1580+
fd,
1581+
source_fd,
1582+
target_fd,
1583+
data,
1584+
flags,
1585+
);
1586+
sqe.user_data = user_data;
1587+
return sqe;
1588+
}
1589+
1590+
/// Queues (but does not submit) an SQE to send a direct file descriptor to
1591+
/// another ring. See `msg_ring_fd()`
1592+
/// `msg_ring_fd_alloc()` is similar to `msg_ring_fd()`, but doesn't specify a
1593+
/// target_fd for the descriptor. Instead, this target_fd is allocated in the
1594+
/// target ring and returned in the CQE res field.
1595+
/// Returns a pointer to the SQE.
1596+
pub fn msg_ring_fd_alloc(
1597+
self: *IoUring,
1598+
user_data: u64,
1599+
fd: linux.fd_t,
1600+
source_fd: linux.fd_t,
1601+
data: u64,
1602+
flags: uflags.MsgRing,
1603+
) !*Sqe {
1604+
const sqe = try self.get_sqe();
1605+
sqe.prep_msg_ring_fd_alloc(
1606+
fd,
1607+
source_fd,
1608+
data,
1609+
flags,
1610+
);
1611+
sqe.user_data = user_data;
1612+
return sqe;
1613+
}
1614+
1615+
/// Queues (but does not submit) an SQE to prepares a request to get an
1616+
/// extended attribute value
1617+
/// Returns a pointer to the SQE.
1618+
pub fn getxattr(
1619+
self: *IoUring,
1620+
user_data: u64,
1621+
name: []const u8,
1622+
value: []const u8,
1623+
path: []const u8,
1624+
len: u32,
1625+
) !*Sqe {
1626+
const sqe = try self.get_sqe();
1627+
sqe.prep_getxattr(name, value, path, len);
1628+
sqe.user_data = user_data;
1629+
return sqe;
1630+
}
1631+
1632+
/// Queues (but does not submit) an SQE to prepares a request to set an
1633+
/// extended attribute value
1634+
/// Returns a pointer to the SQE.
1635+
pub fn setxattr(
1636+
self: *IoUring,
1637+
user_data: u64,
1638+
name: []const u8,
1639+
value: []const u8,
1640+
path: []const u8,
1641+
flags: linux.SetXattr,
1642+
len: u32,
1643+
) !*Sqe {
1644+
const sqe = try self.get_sqe();
1645+
sqe.prep_setxattr(name, value, path, flags, len);
1646+
sqe.user_data = user_data;
1647+
return sqe;
1648+
}
1649+
15191650
/// Queues (but does not submit) an SQE to perform a `waitid(2)`.
15201651
/// Returns a pointer to the SQE.
15211652
pub fn waitid(
@@ -2819,6 +2950,116 @@ pub const Sqe = extern struct {
28192950
sqe.rw_flags = @bitCast(flags);
28202951
}
28212952

2953+
pub fn prep_msg_ring(
2954+
sqe: *Sqe,
2955+
fd: linux.fd_t,
2956+
len: u32,
2957+
data: u64,
2958+
flags: uflags.MsgRing,
2959+
) void {
2960+
sqe.prep_rw(
2961+
.msg_ring,
2962+
fd,
2963+
undefined,
2964+
len,
2965+
data,
2966+
);
2967+
sqe.rw_flags = @bitCast(flags);
2968+
}
2969+
2970+
pub fn prep_msg_ring_cqe_flags(
2971+
sqe: *Sqe,
2972+
fd: linux.fd_t,
2973+
len: u32,
2974+
data: u64,
2975+
msg_flags: uflags.MsgRing,
2976+
cqe_flags: Cqe.Flags,
2977+
) void {
2978+
const enable_flags_pass = blk: {
2979+
var flags = msg_flags;
2980+
flags.flags_pass = true;
2981+
break :blk flags;
2982+
};
2983+
sqe.prep_msg_ring(fd, len, data, enable_flags_pass);
2984+
// sqe.file_index in liburing maps to splice_fd_in in Zig sqe
2985+
sqe.splice_fd_in = @intCast(@as(u32, @bitCast(cqe_flags)));
2986+
}
2987+
2988+
pub fn prep_msg_ring_fd(
2989+
sqe: *Sqe,
2990+
fd: linux.fd_t,
2991+
source_fd: linux.fd_t,
2992+
target_fd: linux.fd_t,
2993+
data: u64,
2994+
flags: uflags.MsgRing,
2995+
) void {
2996+
sqe.prep_rw(
2997+
.msg_ring,
2998+
fd,
2999+
@ptrFromInt(@intFromEnum(MsgRingCmd.send_fd)),
3000+
0,
3001+
data,
3002+
);
3003+
sqe.addr3 = @intCast(source_fd);
3004+
sqe.rw_flags = @bitCast(flags);
3005+
sqe.set_target_fixed_file(@intCast(target_fd));
3006+
}
3007+
3008+
pub fn prep_msg_ring_fd_alloc(
3009+
sqe: *Sqe,
3010+
fd: linux.fd_t,
3011+
source_fd: linux.fd_t,
3012+
data: u64,
3013+
flags: uflags.MsgRing,
3014+
) void {
3015+
sqe.prep_rw(
3016+
.msg_ring,
3017+
fd,
3018+
@ptrFromInt(@intFromEnum(MsgRingCmd.send_fd)),
3019+
0,
3020+
data,
3021+
);
3022+
sqe.addr3 = @intCast(source_fd);
3023+
sqe.rw_flags = @bitCast(flags);
3024+
sqe.set_target_fixed_file(constants.FILE_INDEX_ALLOC);
3025+
}
3026+
3027+
pub fn prep_getxattr(
3028+
sqe: *Sqe,
3029+
name: []const u8,
3030+
value: []const u8,
3031+
path: []const u8,
3032+
len: u32,
3033+
) void {
3034+
sqe.prep_rw(
3035+
.getxattr,
3036+
0,
3037+
@intFromPtr(name.ptr),
3038+
len,
3039+
@intFromPtr(value.ptr),
3040+
);
3041+
sqe.addr3 = @intFromPtr(path.ptr);
3042+
}
3043+
3044+
pub fn prep_setxattr(
3045+
sqe: *Sqe,
3046+
name: []const u8,
3047+
value: []const u8,
3048+
path: []const u8,
3049+
flags: linux.SetXattr,
3050+
len: u32,
3051+
) void {
3052+
sqe.prep_rw(
3053+
.setxattr,
3054+
0,
3055+
@intFromPtr(name.ptr),
3056+
len,
3057+
@intFromPtr(value.ptr),
3058+
);
3059+
sqe.addr3 = @intFromPtr(path.ptr);
3060+
sqe.rw_flags = @bitCast(flags);
3061+
}
3062+
28223063
pub fn prep_files_update(
28233064
sqe: *Sqe,
28243065
fds: []const linux.fd_t,

0 commit comments

Comments
 (0)